Windows Research Kernel 1.2 source code
This commit is contained in:
commit
d2d851979c
.gitignoreBuild.batClean.batGetting started with WRK.docLICENSE.txtREADME.txtRebuild.batWRK.slnWRK.vcprojWRK.vcxprojWRK.vcxproj.filtersWRKDebug.batWRKEnv.bat
WS03SP1HALS/x86
base
inc
ntos
BUILD
VDM/i386
VERIFIER
halverifier.hvfbugcheck.hvfddi.hvfdeadlock.hvfdebug.hvfdef.hvfdevobj.hvffilter.hvfgeneric.hvfinit.hvfirp.hvfirpdb.hvfirplog.hvfmacro.hvfmajor.hvfmessage.hvfpacket.hvfpnp.hvfpower.hvfpragma.hvfprint.hvfrandom.hvfsettings.hvfstack.hvftriage.hvfutil.hvfwmi.hvfzwapi.h
cache
config
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
.vs/
|
||||
12
Build.bat
Normal file
12
Build.bat
Normal file
@ -0,0 +1,12 @@
|
||||
@ECHO OFF
|
||||
IF [%2] EQU [] goto setenv
|
||||
set path=%2\tools\%1;%path%
|
||||
set wrkarch=%1
|
||||
goto dothejob
|
||||
:setenv
|
||||
call WRKEnv.bat %1
|
||||
:dothejob
|
||||
cd base\ntos\
|
||||
nmake -nologo %wrkarch%=
|
||||
cd ..\..
|
||||
|
||||
11
Clean.bat
Normal file
11
Clean.bat
Normal file
@ -0,0 +1,11 @@
|
||||
IF [%2] EQU [] goto setenv
|
||||
set path=%2\tools\%1;%path%
|
||||
set wrkarch=%1
|
||||
goto dothejob
|
||||
:setenv
|
||||
call WRKEnv.bat %1
|
||||
:dothejob
|
||||
cd base\ntos\
|
||||
nmake %wrkarch%= clean
|
||||
cd ..\..
|
||||
|
||||
339
Getting started with WRK.doc
Normal file
339
Getting started with WRK.doc
Normal file
@ -0,0 +1,339 @@
|
||||
|
||||
Getting Started with the Windows Research Kernel (WRK)
|
||||
Version 1.23 – Thursday April 23, 2009
|
||||
|
||||
Marty Humphrey, Associate Professor, Department of Computer Science,
|
||||
University of Virginia
|
||||
Brian Burns, Program Manager, Microsoft
|
||||
Serge Lidin, Software Design Engineer, Microsoft
|
||||
|
||||
The purpose of this document is to illustrate how to compile, modify, and
|
||||
use the Windows Research Kernel (WRK). The basic idea is that you will edit
|
||||
and recompile the WRK on a Windows computer, and then run it on a virtual
|
||||
machine running Windows Server 2003. The virtual machine will run in the
|
||||
Virtual PC 2007 environment, which in turn runs under the host Windows OS.
|
||||
The host OS may be Windows Server 2003 or later, or Windows XP or later.
|
||||
This document contains the steps you can take to install everything you
|
||||
need to edit, compile, and run the WRK. The final section of this document
|
||||
describes how to modify the WRK source code, recompile your kernel, and
|
||||
confirm that your changes are executed by attaching a kernel debugger to
|
||||
the virtual machine. Throughout this document, there are nine self-study
|
||||
questions.
|
||||
|
||||
The intended audience of this document are new users to the WRK with
|
||||
limited knowledge of the Windows operating system. No special knowledge of
|
||||
operating system design and/or implementation is necessary to perform the
|
||||
steps in this document. Editing the WRK can be accomplished by any text
|
||||
editor, and compilation of the WRK utilizes the nmake utility that is
|
||||
installed with the WRK sources.
|
||||
|
||||
|
||||
General Information
|
||||
|
||||
|
||||
1. You will need to work rather extensively with the console (Windows
|
||||
Command Prompt) windows. To start a fresh console window, use
|
||||
selections (Start ( All Programs ( Accessories ( Command Prompt) OR
|
||||
(Start ( Run), then type “cmd” and click OK or press Enter.
|
||||
2. To execute a command in the console window, type this command and
|
||||
press Enter.
|
||||
3. There are four components you need to have installed on your machine:
|
||||
Windows Debugger, Virtual PC 2007, virtual machine image of Windows
|
||||
Server 2003 SP1 (with virtual hard drive image), and the WRK itself
|
||||
including source code, tools and binaries. Installation of virtual
|
||||
machine with its hard drive image and of WRK boils down to simple
|
||||
copying them to specified directories.
|
||||
4. You can install all the components separately from respective entries
|
||||
on the DVD or you can install everything using file
|
||||
WRKCompleteInstall.bat residing in the root of the DVD.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Working with WRKCompleteInstall.bat
|
||||
|
||||
|
||||
The WRKCompleteInstall.bat takes four parameters specifying destination
|
||||
directories of the components being installed:
|
||||
/i <virtual_machine_directory>
|
||||
/w <WRK_directory>
|
||||
/d <debugger_directory>
|
||||
/v <Virtual_PC_directory>
|
||||
|
||||
The default destination directories are as follows:
|
||||
WRK: C:\WRK-v1.2\
|
||||
Virtual machine: C:\WRK-v1.2\Win2k3SP1 Image\
|
||||
Debugger: C:\Program Files\Debugging Tools for Windows\
|
||||
Virtual PC: C:\Program Files\Microsoft Virtual PC\
|
||||
|
||||
If you don’t mind the components to be installed to their default
|
||||
destinations, invoke WRKCompleteInstall.bat without parameters by opening
|
||||
Windows Explorer (double-click on “Computer” icon on your desktop),
|
||||
selecting the DVD drive, and double-clicking on WRKCompleteInstall.bat
|
||||
entry.
|
||||
|
||||
Alternatively, you can run WRKCompleteInstall.bat from a console window,
|
||||
with or without parameters:
|
||||
1. Open Windows Explorer and find out what is the letter of your DVD
|
||||
drive (let it be, say, F).
|
||||
2. Open console window, type F: and press Enter; you have switched to
|
||||
your DVD drive.
|
||||
3. Now type WRKCompleteInstall and press Enter to install the components
|
||||
to default destinations
|
||||
4. OR specify the destinations, for example:
|
||||
WRKCompleteInstall /i C:\WRK_VM /w C:\WRK /d C:\WinDbg /v C:\VPC
|
||||
|
||||
If the full name (path) of a destination directory contains space symbol,
|
||||
the whole path should be enclosed in double quotes, for example: /d
|
||||
“C:\Program Files\WinDbg”
|
||||
|
||||
The destination directories should not yet exist on your drive. If the
|
||||
batch file detects that a destination directory already exists, it skips
|
||||
installation of respective component.
|
||||
|
||||
This is done to enable the batch file to perform partial installations. For
|
||||
example, if you already have Virtual PC 2007 installed on your computer,
|
||||
specify its installation directory in /v parameter, and installation of
|
||||
Virtual PC 2007 will be skipped.
|
||||
|
||||
|
||||
Copying WRK Separately
|
||||
|
||||
|
||||
To copy the WRK (presuming you have the other three components already
|
||||
installed) to your machine, follow these steps:
|
||||
- open a console window;
|
||||
- switch to DVD drive;
|
||||
- execute command cd \Resources\Windows_Research_Kernel\Get_WRK
|
||||
- execute command WRKCopy /w <destination_directory>
|
||||
(if you run WRKCopy.bat without parameters, WRK will be copied to C:\WRK-
|
||||
v1.2\);
|
||||
ALTERNATIVELY
|
||||
- open Windows Explorer;
|
||||
- create the destination directory on your hard drive;
|
||||
- switch to DVD drive;
|
||||
- navigate to \Resources\Windows_Research_Kernel\Get_WRK\WRK-v1.2\;
|
||||
- select all files and subdirectories, drag and drop them to the
|
||||
destination directory.
|
||||
|
||||
|
||||
|
||||
|
||||
Exercise #1: Building the WRK
|
||||
|
||||
|
||||
|
||||
Windows Research Kernel can be built from Visual Studio 2008 environment or
|
||||
from a console window.
|
||||
|
||||
To build WRK from command line:
|
||||
- open console window;
|
||||
- switch to the directory WRK was copied to (for example, cd \WRK-v1.2);
|
||||
- execute Build <arch> (or Rebuild <arch> or Clean <arch>), see note about
|
||||
<arch> below;
|
||||
OR
|
||||
- open console window;
|
||||
- switch to the directory WRK was copied to;
|
||||
- execute WRKEnv <arch>, see note about <arch> below;
|
||||
- execute cd base\ntos
|
||||
- execute nmake %wrkarch%=
|
||||
|
||||
To build WRK in VS2008 environment:
|
||||
- start VS2008;
|
||||
- open solution <WRK_DIR>\WRK.sln, where <WRK_DIR> is the directory WRK was
|
||||
copied to;
|
||||
- make sure the Configuration is amd64/Win32 or x86/Win32, as is
|
||||
appropriate;
|
||||
- select Build/Build Solution (or Rebuild Solution, or Clean Solution).
|
||||
|
||||
NOTE: don’t start the build before looking at question #Q-1, below!
|
||||
|
||||
The built kernel is located in c:\WRK-v1.2\base\ntos\BUILD\EXE as
|
||||
wrkx86.exe .
|
||||
|
||||
NOTE ABOUT <arch>
|
||||
|
||||
Batch files Build.bat, Rebuild.bat, Clean.bat, WRKEnv.bat and WRKDebug.bat
|
||||
take one parameter – target architecture, which is x86 or amd64.
|
||||
For the first use of either of these batch files, default target
|
||||
architecture is x86.
|
||||
Once the target architecture was defined (explicitly or by default), it
|
||||
cannot be changed for current console window, and <arch> parameter of the
|
||||
batch files is ignored.
|
||||
The title of the window where the WRK environment has been set to some
|
||||
target architecture changes to “WRK x86” or “WRK amd64”.
|
||||
To work with different target architecture, open another console window.
|
||||
|
||||
Questions for this exercise:
|
||||
1. How long did it take to compile your kernel the first time? If you run
|
||||
the same command a second time (step #5, above), how long does it take?
|
||||
(It is sufficient in this case to “eye-ball” it – ‘seconds’ resolution is
|
||||
fine).
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Exercise #2: Running Windows Server 2003 inside Virtual PC 2007
|
||||
|
||||
|
||||
1. A fully configured Virtual PC 2007 virtual machine has been provided on
|
||||
this DVD for you to run the WRK. If the default installation options were
|
||||
used, it is located in the directory
|
||||
C:\WRK-v1.2\Win2k3SP1 Image\
|
||||
2. Start Virtual PC 2007 (Start ( All Programs ( Microsoft Virtual PC).
|
||||
This will start the “New Virtual Machine Wizard”:
|
||||
a. “Add an existing virtual machine”
|
||||
b. Browse to c:\WRK-v1.2\Win2k3SP1 Image\ (or whatever directory you
|
||||
chose with WRKCompleteInstall.bat) and choose the file “Win2k3 SP1
|
||||
WRK.vmc”
|
||||
c. Click Next ( Finish, making sure the “When I click Finish, open
|
||||
Settings” box is checked.
|
||||
3. The settings windows for “Win2k3 SP1 WRK” should now be open. Please
|
||||
note the following:
|
||||
a. “Undo Disks” is disabled. Any changes you make to the virtual
|
||||
machine will be written to the hard disk. If you want the option of
|
||||
throwing out any changes you make when you turn off the virtual
|
||||
machine, enable this option.
|
||||
b. The named pipe \\.\pipe\debug is configured on COM1. This allows
|
||||
WinDbg to connect to the WRK within the Virtual PC 2007
|
||||
environment.
|
||||
c. “Virtual Machine Additions” are installed, enabling “pointer
|
||||
integration”. “Virtual Machine Additions” allow a tighter
|
||||
connection between the host machine and the Virtual Machine (for
|
||||
example, the performance of the virtual machine will be better, you
|
||||
can resize the Virtual Machine window, and you will be able to drag-
|
||||
and-drop from the physical machine to the virtual machine).
|
||||
i. Note: upon rebooting the Virtual Machine, the way to get
|
||||
“Ctrl-Alt-Delete” to the Virtual Machine is via the Virtual
|
||||
Machine’s “Action” menu.
|
||||
d. The “Shared Folder” c:\ ( z:\ is enabled. This option maps the c:\
|
||||
root directory on the host machine to the z:\ drive on the virtual
|
||||
machine for easy file sharing between the systems.
|
||||
4. Start the “Win2k3 SP1 WRK” virtual machine from within the Virtual PC
|
||||
Console window.
|
||||
5. At the boot prompt, select “Windows Server 2003, Standard”. This option
|
||||
boots the original Windows Server 2003 SP1 kernel. The other options boot
|
||||
the WRK with and without debugging enabled.
|
||||
a. Note: To help people keep track of kernel versions being run, the
|
||||
virtual machine desktop wallpaper has been preconfigured to show
|
||||
the kernel build number.
|
||||
6. The virtual machine has been preconfigured to automatically login to the
|
||||
administrator account without user interaction. If you prefer to use
|
||||
another account or require user login, please use the information
|
||||
provided in SetAutoAdministratorLogon.zip on the virtual machine desktop
|
||||
to modify this behavior.
|
||||
7. Give your physical machine a name unique to you to prevent any domain
|
||||
naming conflicts.
|
||||
a. Right click on My Computer ( Properties (Computer Name (Change
|
||||
b. You can also add the virtual machine to a domain if you wish. It is
|
||||
preconfigured to be part of the generic workgroup “WORKGROUP”
|
||||
8. Note: Windows update is turned “off” to prevent SP2 from being installed
|
||||
in the virtual machine. SP2 is not compatible with the WRK at this time
|
||||
and installing SP2 into the virtual machine can only be reversed if the
|
||||
“Undo Disks” setting is enabled.
|
||||
|
||||
Questions for this exercise:
|
||||
2. How big is the physical file that contains your virtual disk? (Right
|
||||
click on the .vhd file and get “Properties” – not the .vmc file)
|
||||
|
||||
Exercise #3: Monitor the invocation of “QuerySystemInformation”
|
||||
|
||||
In this portion of the lab you will modify the WRK kernel to print out some
|
||||
debugging information to keep track of the number of times
|
||||
“QuerySystemInformation” is invoked (sometimes a developer may wish the
|
||||
kernel is “instrumented” this way for performance purposes – for example,
|
||||
if we find that this function is invoked A LOT, then this function is a
|
||||
reasonable candidate for performance optimization, right?)
|
||||
1. In this first step, we’ll confirm that you can attach a debugger to the
|
||||
kernel (we won’t actually modify the kernel until the next step). Follow
|
||||
the instructions at http://support.microsoft.com/kb/871171/ to attach the
|
||||
kernel debugger to your Virtual Machine (Note that this works for Virtual
|
||||
PC 2007 as well – follow the instructions for Virtual PC 2004). Here is
|
||||
some additional information:
|
||||
a. Start your WRK Virtual Machine if it’s not already running and at
|
||||
the boot prompt, chose the “Windows Server 2003 SP1, WRK [debugger
|
||||
enabled]” option.
|
||||
b. Your virtual machine should sit idle while it waits for the Windows
|
||||
Debugger (WinDbg) to connect.
|
||||
c. Open a console window on the host machine and start the Windows
|
||||
Debugger:
|
||||
- switch to the directory WRK was copied to;
|
||||
- execute WRKDebug <arch> (see note about <arch> in Exercise #1);
|
||||
OR
|
||||
- switch to the directory WRK was copied to;
|
||||
- execute WRKEnv <arch> (see note about <arch> in Exercise #1);
|
||||
- execute WinDbg %windbgargs%
|
||||
d. During the booting activity, you should see a few lines of text on
|
||||
your “WinDbg” window (probably beginning with “Connected to Windows
|
||||
Server 2003 3790 x86 compatible target, ptr64 FALSE”). If not, then
|
||||
re-try, making sure that you selected the debugging kernel to be
|
||||
booted.
|
||||
i. Note: In order to connect to the kernel from WinDbg, you may
|
||||
have to click Debug ( Break in the WinDbg window.
|
||||
e. Once this works, go onto the next step without shutting down your
|
||||
Virtual Machine or your windbdg.exe window. You’ll know it works if
|
||||
you see this info in the debugging window and you’re able to log
|
||||
onto your WRK Virtual Machine.
|
||||
2. Now we will modify the kernel, install it on the Virtual Machine, boot
|
||||
the modified kernel, and see the output on the debugging window. We’ll
|
||||
start by modifying and recompiling our kernel on the physical machine:
|
||||
a. Open a text editor of your choice and edit C:/WRK-
|
||||
v1.2/base/ntos/ex/sysinfo.c
|
||||
b. Get to line 1721 and insert the following line:
|
||||
|
||||
static int NumTimesCalled = 0;
|
||||
|
||||
c. Shortly after this (immediately before the line “Status =
|
||||
STATUS_SUCCESS”), add the following line:
|
||||
|
||||
DbgPrint( “WRK %d: Entering
|
||||
NTQuerySystemInformation!!!\n”,++NumTimesCalled );
|
||||
|
||||
d. Save the file and recompile the kernel as above (Exercise #2) [1]
|
||||
3. Drag-and-drop your new kernel onto the Virtual Machine’s Administrator’s
|
||||
“My Documents” folder (the new kernel will be on the physical machine in
|
||||
C:\WRK-v1.2\base\ntos\BUILD\EXE, with the name wrkx86.exe). Once you have
|
||||
moved it to the Virtual Machine, copy this file on the Virtual Machine to
|
||||
C:\WINDOWS\system32\
|
||||
a. The virtual machine has been preconfigured to boot the WRK and
|
||||
already contains the file wrkx86.exe in C:\WINDOWS\System32. We
|
||||
recommend you back up this file before copying over it with the
|
||||
modified kernel. When this file is copied over, the WRK boot
|
||||
options in the virtual machine will both point to the new kernel.
|
||||
4. Reboot the Virtual Machine via Start ( Shutdown ( Restart. Select the
|
||||
“Windows Server 2003 SP1, WRK [debugger enabled]” boot option and watch
|
||||
the output on the debugging window.
|
||||
a. Note: you’ll probably have to select the debugger window, which
|
||||
may be hidden, and select “no” to the question “Save information
|
||||
for workspace?”)
|
||||
5. If everything is working, you should start seeing something like:
|
||||
WRK 82: Entering NTQuerySystemInformation!!!
|
||||
WRK 83: Entering NTQuerySystemInformation!!!
|
||||
WRK 84: Entering NTQuerySystemInformation!!!
|
||||
If you’re not seeing this, then go back through the instructions to see
|
||||
if you’ve missed something. Note: if your new kernel does not boot, then
|
||||
you can reboot into the “Windows Server 2003, Standard” boot kernel.
|
||||
Questions for this exercise:
|
||||
3. How many times is this function invoked up until right before the
|
||||
Windows login banner appears, right after the WRK Virtual Machine has
|
||||
fully booted?
|
||||
4. Show a small section of the output of the invocation of your debugging
|
||||
statement. To do this, first select the Debugging window and then hit Alt-
|
||||
PrtSc (“print screen”). This will put a copy of the window into the edit
|
||||
buffer, which you can then get at (say in Microsoft Office) via Edit (
|
||||
paste.
|
||||
5. Once you’ve completed that, and closed your Virtual Machine and
|
||||
debugging window, how big is the physical file that contains your virtual
|
||||
disk now? Why is this? (I.e., why is it the same, or why has it changed?)
|
||||
|
||||
That’s it! You have successfully modified the Windows Research Kernel and
|
||||
observed your change in action. By following this basic procedure, you are
|
||||
now able to explore all kinds of kernel modifications and subsequently test
|
||||
the effect of such changes. Our general advice: Always keep a “safe” copy
|
||||
of a kernel bootable via C:\boot.ini – this will allow you to easily revert
|
||||
to a known safe state. Have fun!
|
||||
-----------------------
|
||||
[1] We recommend you make a backup copy of this file before saving the
|
||||
modified version.
|
||||
113
LICENSE.txt
Normal file
113
LICENSE.txt
Normal file
@ -0,0 +1,113 @@
|
||||
Windows Research Kernel Source Code License
|
||||
|
||||
|
||||
This license governs use of the accompanying software, and your use of
|
||||
the software constitutes acceptance of this license. Your license rights
|
||||
below are subject to the restrictions in the license, and are available
|
||||
to you only so long as you remain eligible due to your affiliation with
|
||||
an accredited educational institution. (For more details on eligibility
|
||||
see http://www.microsoft.com/WindowsAcademic).
|
||||
|
||||
You may use and modify this software for any non-commercial purpose within
|
||||
your educational institution, including making a reasonable number of copies.
|
||||
Teaching, academic research, and personal experimentation are examples of
|
||||
purposes which can be non-commercial. You may post copies on an internal
|
||||
secure server, and it may be installed and used on personal machines of
|
||||
eligible users.
|
||||
|
||||
You may distribute snippets of this software in research papers, books or
|
||||
other teaching materials, or publish snippets of the software on websites
|
||||
or on-line community forums that are intended for teaching and research.
|
||||
The total amount of source code in each of your snippets should not
|
||||
exceed 50 lines. If you wish to use a larger portion of the software,
|
||||
please contact compsci@microsoft.com.
|
||||
|
||||
You may not use or distribute this software or any derivative works in
|
||||
any form for commercial purposes. Examples of commercial purposes would
|
||||
be running business operations, licensing, leasing, or selling the software,
|
||||
or distributing the software for use with commercial products.
|
||||
If you wish to commercialize your work related to the software or take
|
||||
part in research with industrial partners, you need to contact
|
||||
iplg@microsoft.com to enquire about a commercial license.
|
||||
|
||||
You may distribute the software and modifications to the software for
|
||||
non-commercial purposes, but only to other eligible users of the
|
||||
software (for example, to another university student or professor to
|
||||
support joint academic research). You may not grant rights to the
|
||||
software or derivative works that are broader than those provided
|
||||
by this license. For example, you may not distribute modifications
|
||||
of the software under terms that would permit commercial use, or under
|
||||
terms that purport to require the software or derivative works to be
|
||||
sublicensed to others.
|
||||
|
||||
You may use any information in intangible form that you remember after
|
||||
accessing the software. However, this right does not grant you a license
|
||||
to any of Microsoft's copyrights or patents for anything you might
|
||||
create using such information.
|
||||
|
||||
In return for the license rights above, you must agree to these obligations:
|
||||
|
||||
1. You will not remove any copyright or other notices from the software,
|
||||
nor reverse engineer or decompile binary portions of the software,
|
||||
unless your laws give you the right to do so despite this restriction.
|
||||
|
||||
2. You will include a verbatim copy of this license if you distribute
|
||||
the software in any form.
|
||||
|
||||
3. If you distribute derivative works of the software in source code
|
||||
form you will do so only under this license, and if you distribute
|
||||
derivative works of the software solely in object form you will do so
|
||||
only under a license that complies with this license.
|
||||
|
||||
4. If you have modified the software or created derivative works,
|
||||
and distribute such modifications or derivative works, you will cause
|
||||
the modified files to carry prominent notices describing your changes
|
||||
and the date of the changes, so that recipients know that they are not
|
||||
receiving the original software.
|
||||
|
||||
5. Microsoft welcomes your comments and suggestions on the source code,
|
||||
which you provide on a strictly voluntary basis. If you give Microsoft
|
||||
comments and suggestions regarding bug fixes, enhancements or other
|
||||
modifications to the source code, you agree that Microsoft may,
|
||||
in connection with Microsoft products and services use, disclose or
|
||||
otherwise commercialize your comments and suggestions entirely without
|
||||
any obligation or restriction based on intellectual property rights or
|
||||
otherwise. You will not give any comments or suggestions that you have
|
||||
reason to believe are subject to any patent, copyright, or other
|
||||
intellectual property claim or right of any third party.
|
||||
|
||||
6. THE SOFTWARE COMES "AS IS", WITH NO WARRANTIES. THIS MEANS NO EXPRESS,
|
||||
IMPLIED OR STATUTORY WARRANTY, INCLUDING WITHOUT LIMITATION, WARRANTIES
|
||||
OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE OR ANY WARRANTY
|
||||
OF TITLE OR NON-INFRINGEMENT. YOU MUST PASS THIS DISCLAIMER ON WHENEVER
|
||||
YOU DISTRIBUTE THE SOFTWARE OR DERIVATIVE WORKS.
|
||||
|
||||
7. MICROSOFT WILL NOT BE LIABLE FOR ANY DAMAGES RELATED TO THE SOFTWARE
|
||||
OR THIS LICENSE, INCLUDING DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL
|
||||
OR INCIDENTAL DAMAGES, TO THE MAXIMUM EXTENT THE LAW PERMITS, NO MATTER
|
||||
WHAT LEGAL THEORY IT IS BASED ON. YOU MUST PASS THIS LIMITATION OF
|
||||
LIABILITY ON WHENEVER YOU DISTRIBUTE THE SOFTWARE OR DERIVATIVE WORKS.
|
||||
|
||||
8. If you sue anyone over patents that you think may apply to the software
|
||||
or anyone's use of the software, your license to the software ends
|
||||
immediately.
|
||||
|
||||
9. You will not use the software to aid the development of any software
|
||||
programs that are designed to:
|
||||
(a) harm or intentionally interfere with the operation of a computer
|
||||
system including any data or information stored on such computer
|
||||
system; and/or
|
||||
(b) surreptitiously gain or maintain high level access to a computer
|
||||
system, self-propagate, and/or execute in a manner that prevents
|
||||
detection, including but not limited to, so-called “rootkit”
|
||||
software programs, viruses, or worms.
|
||||
|
||||
10. Your rights under the license end immediately if you breach it
|
||||
in any way.
|
||||
|
||||
11. Microsoft reserves all rights not expressly granted to you in this
|
||||
license.
|
||||
|
||||
|
||||
License Version: 5 December 2008.
|
||||
|
||||
148
README.txt
Normal file
148
README.txt
Normal file
@ -0,0 +1,148 @@
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of
|
||||
the Windows Research Kernel Source Code License agreement
|
||||
(see License.txt). If you do not agree to the terms, do not use the code.
|
||||
|
||||
***
|
||||
|
||||
WRK v1.2
|
||||
|
||||
The Windows Research Kernel v1.2 contains the sources for the core of
|
||||
the Windows (NTOS) kernel and a build environment for a kernel that will run on
|
||||
x86 (Windows Server 2003 Service Pack 1) and
|
||||
amd64 (Windows XP x64 Professional)
|
||||
A future version may also support booting WRK kernels on Windows XP x86 systems,
|
||||
but the current kernels will fail to boot due to differences in some shared
|
||||
structures.
|
||||
|
||||
The NTOS kernel implements the basic OS functions
|
||||
for processes, threads, virtual memory and cache managers, I/O management,
|
||||
the registry, executive functions such as the kernel heap and synchronization,
|
||||
the object manager, the local procedure call mechanism, the security reference
|
||||
monitor, low-level CPU management (thread scheduling, Asynchronous and Deferred
|
||||
Procedure calls, interrupt/trap handling, exceptions), etc.
|
||||
|
||||
The NT Hardware Abstraction Layer, file systems, network stacks, and device
|
||||
drivers are implemented separately from NTOS and loaded into kernel mode
|
||||
as dynamic libraries. Sources for these dynamic components are not included
|
||||
in the WRK, but some are available in various development kits published
|
||||
by Microsoft, such as the Installable File System (IFS) Kit and the
|
||||
Windows Driver Development Kit (DDK).
|
||||
|
||||
WRK v1.2 includes most of the NTOS kernel sources from the latest released
|
||||
version of Windows, which supports the AMD64 architecture on the Desktop.
|
||||
The kernel sources excluded from the kit are primarily in the areas of
|
||||
plug-and-play, power management, the device verifier, kernel debugger
|
||||
interface, and virtual dos machine. The primary modifications to WRK
|
||||
from the released kernel are related to cleanup and removal of server
|
||||
support, such as code related to the Intel IA64.
|
||||
|
||||
***
|
||||
|
||||
Organization of the WRK sources
|
||||
|
||||
The file License.txt contains the license covering use of the WRK.
|
||||
|
||||
The public\ directory contains a number of include files shared among system
|
||||
components. base\ntos\ contains the NTOS sources.
|
||||
|
||||
The primary NTOS source components included in the WRK are organized as follows:
|
||||
|
||||
cache\ - cache manager
|
||||
config\ - registry implementation
|
||||
dbgk\ - user-mode debugger support
|
||||
ex\ - executive functions (kernel heap, synchronization, time)
|
||||
fsrtl\ - file system run-time support
|
||||
io\ - I/O manager
|
||||
ke\ - scheduler, CPU management, low-level synchronization
|
||||
lpc\ - local procedure call implementation
|
||||
mm\ - virtual memory manager
|
||||
ob\ - kernel object manager
|
||||
ps\ - process/thread support
|
||||
se\ - security functions
|
||||
wmi\ - Windows Management Instrumentation
|
||||
|
||||
inc\ - NTOS-only include files
|
||||
rtl\ - kernel run-time support
|
||||
init\ - kernel startup
|
||||
|
||||
***
|
||||
|
||||
Copying and building the WRK
|
||||
|
||||
WRK can be built on Windows Server 2003 or later, or on Windows XP or later.
|
||||
|
||||
To copy WRK to your machine:
|
||||
- open a console window;
|
||||
- switch to DVD;
|
||||
- switch to \Resources\Windows_Research_Kernel\Get_WRK\;
|
||||
- run WRKCopy.bat /w <destination_directory>
|
||||
(if you run WRKCopy.bat without parameters, WRK will be copied to C:\WRK-v1.2\);
|
||||
ALTERNATIVELY
|
||||
- open Windows Explorer (MyComputer);
|
||||
- create the destination directory on your hard drive;
|
||||
- switch to DVD;
|
||||
- navigate to \Resources\Windows_Research_Kernel\Get_WRK\WRK-v1.2\;
|
||||
- select all files and subdirectories, drag and drop them to the destination
|
||||
directory.
|
||||
|
||||
To adjust the WRK environment setting batch file:
|
||||
- open console window;
|
||||
- switch to the directory WRK was copied to;
|
||||
- run Notepad WRKEnv.bat;
|
||||
- make sure the "set path=..." statement contains the directory WinDbg was
|
||||
installed to; (unchanged WRKEnv.bat refers to default directory
|
||||
C:\Program Files\Debugging Tools for Windows);
|
||||
- save the file and exit Notepad.
|
||||
|
||||
To build WRK from command line:
|
||||
- open console window;
|
||||
- switch to the directory WRK was copied to;
|
||||
- run Build <arch> (or Rebuild <arch> or Clean <arch>), see note about <arch>
|
||||
below;
|
||||
ALTERNATIVELY
|
||||
- open console window;
|
||||
- switch to the directory WRK was copied to;
|
||||
- run WRKEnv <arch>, see note about <arch> below;
|
||||
- switch to base\ntos;
|
||||
- run nmake %wrkarch%=
|
||||
|
||||
To build WRK in Visual Studio 2008 environment:
|
||||
- start VS2008;
|
||||
- open solution <WRK_DIR>\WRK.sln, where <WRK_DIR> is the directory WRK was
|
||||
copied to;
|
||||
- make sure the configuration is amd64/Win32 or x86/Win32, as is appropriate;
|
||||
- select Build/Build Solution (or Rebuild Solution, or Clean Solution).
|
||||
|
||||
To start Windows Debugger from command line:
|
||||
- open console window;
|
||||
- switch to the directory WRK was copied to;
|
||||
- run WRKDebug <arch>, see note about <arch> below;
|
||||
ALTERNATIVELY
|
||||
- open console window;
|
||||
- switch to the directory WRK was copied to;
|
||||
- run WRKEnv <arch>, see note about <arch> below;
|
||||
- run WinDbg %windbgargs%
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
NOTE ABOUT <ARCH>
|
||||
|
||||
Batch files Build.bat, Rebuild.bat, Clean.bat, WRKEnv.bat and WRKDebug.bat
|
||||
take one parameter – target architecture, which is x86 or amd64.
|
||||
|
||||
For the first use of either of these batch files, default target architecture
|
||||
is x86.
|
||||
|
||||
Once the target architecture was defined (explicitly or by default), it
|
||||
cannot be changed for current console window, and <arch> parameter of the
|
||||
batch files is ignored.
|
||||
|
||||
The title of the window where the WRK environment has been set to some target
|
||||
architecture changes to “WRK x86” or “WRK amd64”.
|
||||
|
||||
To work with different target architecture, open another console window.
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
***
|
||||
5
Rebuild.bat
Normal file
5
Rebuild.bat
Normal file
@ -0,0 +1,5 @@
|
||||
@ECHO OFF
|
||||
call clean.bat %1 %2
|
||||
call build.bat %1 %2
|
||||
|
||||
|
||||
19
WRK.sln
Normal file
19
WRK.sln
Normal file
@ -0,0 +1,19 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 10.00
|
||||
# Visual Studio 2008
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WindowsResearchKernel", "WRK.vcproj", "{7B312FB7-F0A3-41FE-89D1-6100FDC35009}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
amd64|Win32 = amd64|Win32
|
||||
x86|Win32 = x86|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{7B312FB7-F0A3-41FE-89D1-6100FDC35009}.amd64|Win32.ActiveCfg = amd64|Win32
|
||||
{7B312FB7-F0A3-41FE-89D1-6100FDC35009}.amd64|Win32.Build.0 = amd64|Win32
|
||||
{7B312FB7-F0A3-41FE-89D1-6100FDC35009}.x86|Win32.ActiveCfg = x86|Win32
|
||||
{7B312FB7-F0A3-41FE-89D1-6100FDC35009}.x86|Win32.Build.0 = x86|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
2770
WRK.vcproj
Normal file
2770
WRK.vcproj
Normal file
File diff suppressed because it is too large
Load Diff
708
WRK.vcxproj
Normal file
708
WRK.vcxproj
Normal file
@ -0,0 +1,708 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="amd64|Win32">
|
||||
<Configuration>amd64</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="x86|Win32">
|
||||
<Configuration>x86</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectName>WindowsResearchKernel</ProjectName>
|
||||
<ProjectGuid>{7B312FB7-F0A3-41FE-89D1-6100FDC35009}</ProjectGuid>
|
||||
<RootNamespace>WindowsResearchKernel</RootNamespace>
|
||||
<Keyword>MakeFileProj</Keyword>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='amd64|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Makefile</ConfigurationType>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='x86|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Makefile</ConfigurationType>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='amd64|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='x86|Win32'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>14.0.25123.0</_ProjectFileVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='x86|Win32'">
|
||||
<OutDir>$(SolutionDir)$(Configuration)\</OutDir>
|
||||
<IntDir>$(SolutionDir)base\ntos\BUILD\$(Configuration)\</IntDir>
|
||||
<NMakeBuildCommandLine>"$(SolutionDir)build.bat" $(Configuration) $(SolutionDir)</NMakeBuildCommandLine>
|
||||
<NMakeReBuildCommandLine>"$(SolutionDir)rebuild.bat" $(Configuration) $(SolutionDir)</NMakeReBuildCommandLine>
|
||||
<NMakeCleanCommandLine>"$(SolutionDir)clean.bat" $(Configuration) $(SolutionDir)</NMakeCleanCommandLine>
|
||||
<NMakeOutput />
|
||||
<NMakePreprocessorDefinitions>_X86_=1;i386=1;STD_CALL;FPO=0;CONDITION_HANDLING=1;WRK_MEMORY_MANAGEMENT;NT_INST=0;WIN32=100;_NT1X_=100;WINNT=1;_WIN32_WINNT=0x0502;WINVER=0x0502;_WIN32_IE=0x0603;WIN32_LEAN_AND_MEAN=1;DBG=0;DEVL=1;__BUILDMACHINE__=WRK1.2(university);NDEBUG;_NTSYSTEM_;NT_SMT;NTOS_KERNEL_RUNTIME=1;$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
|
||||
<NMakeIncludeSearchPath>$(SolutionDir)base\ntos\se;$(SolutionDir)base\ntos\rtl;$(SolutionDir)base\ntos\raw;$(SolutionDir)base\ntos\ps;$(SolutionDir)base\ntos\perf;$(SolutionDir)base\ntos\ob;$(SolutionDir)base\ntos\mm;$(SolutionDir)base\ntos\lpc;$(SolutionDir)base\ntos\ke;$(SolutionDir)base\ntos\io\iomgr;$(SolutionDir)base\ntos\io;$(SolutionDir)base\ntos\init;$(SolutionDir)base\ntos\fstub;$(SolutionDir)base\ntos\fsrtl;$(SolutionDir)base\ntos\ex;$(SolutionDir)base\ntos\dbgk;$(SolutionDir)base\ntos\config;$(SolutionDir)base\ntos\cache;$(SolutionDir)public\halkit\inc;$(SolutionDir)public\sdk\inc\crt;$(SolutionDir)public\sdk\inc;$(SolutionDir)public\internal\base\inc;$(SolutionDir)base\inc;$(SolutionDir)public\internal\sdktools\inc;$(SolutionDir)public\internal\ds\inc;$(SolutionDir)public\ddk\inc;..\$(Configuration);$(SolutionDir)base\ntos\$(ProjectName);$(SolutionDir)base\ntos\inc;$(NMakeIncludeSearchPath)</NMakeIncludeSearchPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='amd64|Win32'">
|
||||
<OutDir>$(SolutionDir)$(Configuration)\</OutDir>
|
||||
<IntDir>base\ntos\BUILD\$(Configuration)\</IntDir>
|
||||
<NMakeBuildCommandLine>"$(SolutionDir)build.bat" $(Configuration) $(SolutionDir)</NMakeBuildCommandLine>
|
||||
<NMakeReBuildCommandLine>"$(SolutionDir)rebuild.bat" $(Configuration) $(SolutionDir)</NMakeReBuildCommandLine>
|
||||
<NMakeCleanCommandLine>"$(SolutionDir)clean.bat" $(Configuration) $(SolutionDir)</NMakeCleanCommandLine>
|
||||
<NMakeOutput />
|
||||
<NMakePreprocessorDefinitions>_WIN64;_AMD64_;AMD64CONDITION_HANDLING=1;NT_INST=0;WIN32=100;_NT1X_=100; WINNT=1;_WIN32_WINNT=0x0502;WINVER=0x0502;_WIN32_IE=0x0603;WIN32_LEAN_AND_MEAN=1;DBG=0;DEVL=1;__BUILDMACHINE__=WRK1.2(university);NDEBUG;_NTSYSTEM_;NT_SMT;NTOS_KERNEL_RUNTIME=1;$(NMakePreprocessorDefinitions)</NMakePreprocessorDefinitions>
|
||||
<NMakeIncludeSearchPath>$(SolutionDir)base\ntos\se;$(SolutionDir)base\ntos\rtl;$(SolutionDir)base\ntos\raw;$(SolutionDir)base\ntos\ps;$(SolutionDir)base\ntos\perf;$(SolutionDir)base\ntos\ob;$(SolutionDir)base\ntos\mm;$(SolutionDir)base\ntos\lpc;$(SolutionDir)base\ntos\ke;$(SolutionDir)base\ntos\io\iomgr;$(SolutionDir)base\ntos\io;$(SolutionDir)base\ntos\init;$(SolutionDir)base\ntos\fstub;$(SolutionDir)base\ntos\fsrtl;$(SolutionDir)base\ntos\ex;$(SolutionDir)base\ntos\dbgk;$(SolutionDir)base\ntos\config;$(SolutionDir)base\ntos\cache;$(SolutionDir)public\halkit\inc;$(SolutionDir)public\sdk\inc\crt;$(SolutionDir)public\sdk\inc;$(SolutionDir)public\internal\base\inc;$(SolutionDir)base\inc;$(SolutionDir)public\internal\sdktools\inc;$(SolutionDir)public\internal\ds\inc;$(SolutionDir)public\ddk\inc;..\$(Configuration);$(SolutionDir)base\ntos\$(ProjectName);$(SolutionDir)base\ntos\inc;$(NMakeIncludeSearchPath)</NMakeIncludeSearchPath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="base\ntos\cache\cachedat.c" />
|
||||
<ClCompile Include="base\ntos\cache\cachesub.c" />
|
||||
<ClCompile Include="base\ntos\cache\ccperf.c" />
|
||||
<ClCompile Include="base\ntos\cache\copysup.c" />
|
||||
<ClCompile Include="base\ntos\cache\fssup.c" />
|
||||
<ClCompile Include="base\ntos\cache\lazyrite.c" />
|
||||
<ClCompile Include="base\ntos\cache\logsup.c" />
|
||||
<ClCompile Include="base\ntos\cache\mdlsup.c" />
|
||||
<ClCompile Include="base\ntos\cache\pinsup.c" />
|
||||
<ClCompile Include="base\ntos\cache\vacbsup.c" />
|
||||
<ClCompile Include="base\ntos\config\cmalloc.c" />
|
||||
<ClCompile Include="base\ntos\config\cmapi.c" />
|
||||
<ClCompile Include="base\ntos\config\cmapi2.c" />
|
||||
<ClCompile Include="base\ntos\config\cmboot.c" />
|
||||
<ClCompile Include="base\ntos\config\cmchek.c" />
|
||||
<ClCompile Include="base\ntos\config\cmchek2.c" />
|
||||
<ClCompile Include="base\ntos\config\cmclose.c" />
|
||||
<ClCompile Include="base\ntos\config\cmconfig.c" />
|
||||
<ClCompile Include="base\ntos\config\cmcontrl.c" />
|
||||
<ClCompile Include="base\ntos\config\cmdat.c" />
|
||||
<ClCompile Include="base\ntos\config\cmdat2.c" />
|
||||
<ClCompile Include="base\ntos\config\cmdatini.c" />
|
||||
<ClCompile Include="base\ntos\config\cmdelay.c" />
|
||||
<ClCompile Include="base\ntos\config\cmdelete.c" />
|
||||
<ClCompile Include="base\ntos\config\cmdown.c" />
|
||||
<ClCompile Include="base\ntos\config\cmgquota.c" />
|
||||
<ClCompile Include="base\ntos\config\cmhook.c" />
|
||||
<ClCompile Include="base\ntos\config\cmhvlist.c" />
|
||||
<ClCompile Include="base\ntos\config\cmindex.c" />
|
||||
<ClCompile Include="base\ntos\config\cminit.c" />
|
||||
<ClCompile Include="base\ntos\config\cmmapvw.c" />
|
||||
<ClCompile Include="base\ntos\config\cmname.c" />
|
||||
<ClCompile Include="base\ntos\config\cmnotify.c" />
|
||||
<ClCompile Include="base\ntos\config\cmparse.c" />
|
||||
<ClCompile Include="base\ntos\config\cmparse2.c" />
|
||||
<ClCompile Include="base\ntos\config\cmquery.c" />
|
||||
<ClCompile Include="base\ntos\config\cmsavres.c" />
|
||||
<ClCompile Include="base\ntos\config\cmse.c" />
|
||||
<ClCompile Include="base\ntos\config\cmsecache.c" />
|
||||
<ClCompile Include="base\ntos\config\cmsubs.c" />
|
||||
<ClCompile Include="base\ntos\config\cmsubs2.c" />
|
||||
<ClCompile Include="base\ntos\config\cmsubs3.c" />
|
||||
<ClCompile Include="base\ntos\config\cmsysini.c" />
|
||||
<ClCompile Include="base\ntos\config\cmtrecpy.c" />
|
||||
<ClCompile Include="base\ntos\config\cmtredel.c" />
|
||||
<ClCompile Include="base\ntos\config\cmtree.c" />
|
||||
<ClCompile Include="base\ntos\config\cmvalue.c" />
|
||||
<ClCompile Include="base\ntos\config\cmwmi.c" />
|
||||
<ClCompile Include="base\ntos\config\cmworker.c" />
|
||||
<ClCompile Include="base\ntos\config\cmwrapr.c" />
|
||||
<ClCompile Include="base\ntos\config\cmwrapr2.c" />
|
||||
<ClCompile Include="base\ntos\config\hivebin.c" />
|
||||
<ClCompile Include="base\ntos\config\hivecell.c" />
|
||||
<ClCompile Include="base\ntos\config\hivechek.c" />
|
||||
<ClCompile Include="base\ntos\config\hivefree.c" />
|
||||
<ClCompile Include="base\ntos\config\hivehint.c" />
|
||||
<ClCompile Include="base\ntos\config\hiveinit.c" />
|
||||
<ClCompile Include="base\ntos\config\hiveload.c" />
|
||||
<ClCompile Include="base\ntos\config\hivemap.c" />
|
||||
<ClCompile Include="base\ntos\config\hivesum.c" />
|
||||
<ClCompile Include="base\ntos\config\hivesync.c" />
|
||||
<ClCompile Include="base\ntos\config\ntapi.c" />
|
||||
<ClCompile Include="base\ntos\dbgk\dbgkobj.c" />
|
||||
<ClCompile Include="base\ntos\dbgk\dbgkport.c" />
|
||||
<ClCompile Include="base\ntos\dbgk\dbgkproc.c" />
|
||||
<ClCompile Include="base\ntos\ex\amd64\wowinfo.c" />
|
||||
<ClCompile Include="base\ntos\ex\callback.c" />
|
||||
<ClCompile Include="base\ntos\ex\callperf.c" />
|
||||
<ClCompile Include="base\ntos\ex\delay.c" />
|
||||
<ClCompile Include="base\ntos\ex\event.c" />
|
||||
<ClCompile Include="base\ntos\ex\eventpr.c" />
|
||||
<ClCompile Include="base\ntos\ex\exatom.c" />
|
||||
<ClCompile Include="base\ntos\ex\exdata.c" />
|
||||
<ClCompile Include="base\ntos\ex\exinit.c" />
|
||||
<ClCompile Include="base\ntos\ex\fmutexc.c" />
|
||||
<ClCompile Include="base\ntos\ex\handle.c" />
|
||||
<ClCompile Include="base\ntos\ex\harderr.c" />
|
||||
<ClCompile Include="base\ntos\ex\keyedevent.c" />
|
||||
<ClCompile Include="base\ntos\ex\lookasid.c" />
|
||||
<ClCompile Include="base\ntos\ex\luid.c" />
|
||||
<ClCompile Include="base\ntos\ex\mutant.c" />
|
||||
<ClCompile Include="base\ntos\ex\nbqueue.c" />
|
||||
<ClCompile Include="base\ntos\ex\pool.c" />
|
||||
<ClCompile Include="base\ntos\ex\probe.c" />
|
||||
<ClCompile Include="base\ntos\ex\profile.c" />
|
||||
<ClCompile Include="base\ntos\ex\pushlock.c" />
|
||||
<ClCompile Include="base\ntos\ex\raise.c" />
|
||||
<ClCompile Include="base\ntos\ex\resource.c" />
|
||||
<ClCompile Include="base\ntos\ex\rundown.c" />
|
||||
<ClCompile Include="base\ntos\ex\semphore.c" />
|
||||
<ClCompile Include="base\ntos\ex\sysinfo.c" />
|
||||
<ClCompile Include="base\ntos\ex\timer.c" />
|
||||
<ClCompile Include="base\ntos\ex\uuid.c" />
|
||||
<ClCompile Include="base\ntos\ex\win32.c" />
|
||||
<ClCompile Include="base\ntos\ex\worker.c" />
|
||||
<ClCompile Include="base\ntos\ex\zone.c" />
|
||||
<ClCompile Include="base\ntos\fsrtl\dbcsname.c" />
|
||||
<ClCompile Include="base\ntos\fsrtl\fastio.c" />
|
||||
<ClCompile Include="base\ntos\fsrtl\faulttol.c" />
|
||||
<ClCompile Include="base\ntos\fsrtl\filelock.c" />
|
||||
<ClCompile Include="base\ntos\fsrtl\filter.c" />
|
||||
<ClCompile Include="base\ntos\fsrtl\filtrctx.c" />
|
||||
<ClCompile Include="base\ntos\fsrtl\fsfilter.c" />
|
||||
<ClCompile Include="base\ntos\fsrtl\fsrtlpc.c" />
|
||||
<ClCompile Include="base\ntos\fsrtl\largemcb.c" />
|
||||
<ClCompile Include="base\ntos\fsrtl\name.c" />
|
||||
<ClCompile Include="base\ntos\fsrtl\notify.c" />
|
||||
<ClCompile Include="base\ntos\fsrtl\oplock.c" />
|
||||
<ClCompile Include="base\ntos\fsrtl\pnp.c" />
|
||||
<ClCompile Include="base\ntos\fsrtl\stackovf.c" />
|
||||
<ClCompile Include="base\ntos\fsrtl\tunnel.c" />
|
||||
<ClCompile Include="base\ntos\fsrtl\unc.c" />
|
||||
<ClCompile Include="base\ntos\fstub\drivesup.c" />
|
||||
<ClCompile Include="base\ntos\init\initos.c" />
|
||||
<ClCompile Include="base\ntos\init\ntkrnlmp.c" />
|
||||
<ClCompile Include="base\ntos\init\ntoskrnl.c" />
|
||||
<ClCompile Include="base\ntos\io\ioguid.c" />
|
||||
<ClCompile Include="base\ntos\io\iomgr\cancelapi.c" />
|
||||
<ClCompile Include="base\ntos\io\iomgr\complete.c" />
|
||||
<ClCompile Include="base\ntos\io\iomgr\create.c" />
|
||||
<ClCompile Include="base\ntos\io\iomgr\dev2dos.c" />
|
||||
<ClCompile Include="base\ntos\io\iomgr\devctrl.c" />
|
||||
<ClCompile Include="base\ntos\io\iomgr\dir.c" />
|
||||
<ClCompile Include="base\ntos\io\iomgr\errorlog.c" />
|
||||
<ClCompile Include="base\ntos\io\iomgr\fsctrl.c" />
|
||||
<ClCompile Include="base\ntos\io\iomgr\internal.c" />
|
||||
<ClCompile Include="base\ntos\io\iomgr\iodata.c" />
|
||||
<ClCompile Include="base\ntos\io\iomgr\ioinit.c" />
|
||||
<ClCompile Include="base\ntos\io\iomgr\iosubs.c" />
|
||||
<ClCompile Include="base\ntos\io\iomgr\loadunld.c" />
|
||||
<ClCompile Include="base\ntos\io\iomgr\lock.c" />
|
||||
<ClCompile Include="base\ntos\io\iomgr\misc.c" />
|
||||
<ClCompile Include="base\ntos\io\iomgr\objsup.c" />
|
||||
<ClCompile Include="base\ntos\io\iomgr\open.c" />
|
||||
<ClCompile Include="base\ntos\io\iomgr\parse.c" />
|
||||
<ClCompile Include="base\ntos\io\iomgr\qsea.c" />
|
||||
<ClCompile Include="base\ntos\io\iomgr\qsfs.c" />
|
||||
<ClCompile Include="base\ntos\io\iomgr\qsinfo.c" />
|
||||
<ClCompile Include="base\ntos\io\iomgr\qsquota.c" />
|
||||
<ClCompile Include="base\ntos\io\iomgr\read.c" />
|
||||
<ClCompile Include="base\ntos\io\iomgr\write.c" />
|
||||
<ClCompile Include="base\ntos\ke\amd64\allproc.c" />
|
||||
<ClCompile Include="base\ntos\ke\amd64\apcuser.c" />
|
||||
<ClCompile Include="base\ntos\ke\amd64\callback.c" />
|
||||
<ClCompile Include="base\ntos\ke\amd64\decode.c" />
|
||||
<ClCompile Include="base\ntos\ke\amd64\exceptn.c" />
|
||||
<ClCompile Include="base\ntos\ke\amd64\flush.c" />
|
||||
<ClCompile Include="base\ntos\ke\amd64\flushtb.c" />
|
||||
<ClCompile Include="base\ntos\ke\amd64\initkr.c" />
|
||||
<ClCompile Include="base\ntos\ke\amd64\intobj.c" />
|
||||
<ClCompile Include="base\ntos\ke\amd64\ipi.c" />
|
||||
<ClCompile Include="base\ntos\ke\amd64\misc.c" />
|
||||
<ClCompile Include="base\ntos\ke\amd64\pat.c" />
|
||||
<ClCompile Include="base\ntos\ke\amd64\queuelock.c" />
|
||||
<ClCompile Include="base\ntos\ke\amd64\runtime.c" />
|
||||
<ClCompile Include="base\ntos\ke\amd64\spinlock.c" />
|
||||
<ClCompile Include="base\ntos\ke\amd64\thredini.c" />
|
||||
<ClCompile Include="base\ntos\ke\apcobj.c" />
|
||||
<ClCompile Include="base\ntos\ke\apcsup.c" />
|
||||
<ClCompile Include="base\ntos\ke\balmgr.c" />
|
||||
<ClCompile Include="base\ntos\ke\bugcheck.c" />
|
||||
<ClCompile Include="base\ntos\ke\config.c" />
|
||||
<ClCompile Include="base\ntos\ke\debug.c" />
|
||||
<ClCompile Include="base\ntos\ke\devquobj.c" />
|
||||
<ClCompile Include="base\ntos\ke\dpclock.c" />
|
||||
<ClCompile Include="base\ntos\ke\dpcobj.c" />
|
||||
<ClCompile Include="base\ntos\ke\dpcsup.c" />
|
||||
<ClCompile Include="base\ntos\ke\eventobj.c" />
|
||||
<ClCompile Include="base\ntos\ke\gateobj.c" />
|
||||
<ClCompile Include="base\ntos\ke\hifreqlk.c" />
|
||||
<ClCompile Include="base\ntos\ke\i386\abiosc.c" />
|
||||
<ClCompile Include="base\ntos\ke\i386\allproc.c" />
|
||||
<ClCompile Include="base\ntos\ke\i386\apcuser.c" />
|
||||
<ClCompile Include="base\ntos\ke\i386\biosc.c" />
|
||||
<ClCompile Include="base\ntos\ke\i386\callback.c" />
|
||||
<ClCompile Include="base\ntos\ke\i386\exceptn.c" />
|
||||
<ClCompile Include="base\ntos\ke\i386\flush.c" />
|
||||
<ClCompile Include="base\ntos\ke\i386\flushtb.c" />
|
||||
<ClCompile Include="base\ntos\ke\i386\gdtsup.c" />
|
||||
<ClCompile Include="base\ntos\ke\i386\i386init.c" />
|
||||
<ClCompile Include="base\ntos\ke\i386\intobj.c" />
|
||||
<ClCompile Include="base\ntos\ke\i386\iopm.c" />
|
||||
<ClCompile Include="base\ntos\ke\i386\kernlini.c" />
|
||||
<ClCompile Include="base\ntos\ke\i386\largepag.c" />
|
||||
<ClCompile Include="base\ntos\ke\i386\ldtsup.c" />
|
||||
<ClCompile Include="base\ntos\ke\i386\misc.c" />
|
||||
<ClCompile Include="base\ntos\ke\i386\mtrr.c" />
|
||||
<ClCompile Include="base\ntos\ke\i386\mtrramd.c" />
|
||||
<ClCompile Include="base\ntos\ke\i386\pat.c" />
|
||||
<ClCompile Include="base\ntos\ke\i386\thredini.c" />
|
||||
<ClCompile Include="base\ntos\ke\i386\trapc.c" />
|
||||
<ClCompile Include="base\ntos\ke\idsched.c" />
|
||||
<ClCompile Include="base\ntos\ke\interobj.c" />
|
||||
<ClCompile Include="base\ntos\ke\kernldat.c" />
|
||||
<ClCompile Include="base\ntos\ke\kevutil.c" />
|
||||
<ClCompile Include="base\ntos\ke\kiinit.c" />
|
||||
<ClCompile Include="base\ntos\ke\miscc.c" />
|
||||
<ClCompile Include="base\ntos\ke\mutntobj.c" />
|
||||
<ClCompile Include="base\ntos\ke\procobj.c" />
|
||||
<ClCompile Include="base\ntos\ke\profobj.c" />
|
||||
<ClCompile Include="base\ntos\ke\queueobj.c" />
|
||||
<ClCompile Include="base\ntos\ke\raisexcp.c" />
|
||||
<ClCompile Include="base\ntos\ke\semphobj.c" />
|
||||
<ClCompile Include="base\ntos\ke\thkemul.c" />
|
||||
<ClCompile Include="base\ntos\ke\thredobj.c" />
|
||||
<ClCompile Include="base\ntos\ke\thredsup.c" />
|
||||
<ClCompile Include="base\ntos\ke\timerobj.c" />
|
||||
<ClCompile Include="base\ntos\ke\timersup.c" />
|
||||
<ClCompile Include="base\ntos\ke\wait.c" />
|
||||
<ClCompile Include="base\ntos\ke\waitsup.c" />
|
||||
<ClCompile Include="base\ntos\ke\xipi.c" />
|
||||
<ClCompile Include="base\ntos\ke\yield.c" />
|
||||
<ClCompile Include="base\ntos\lpc\lpcclose.c" />
|
||||
<ClCompile Include="base\ntos\lpc\lpccompl.c" />
|
||||
<ClCompile Include="base\ntos\lpc\lpcconn.c" />
|
||||
<ClCompile Include="base\ntos\lpc\lpccreat.c" />
|
||||
<ClCompile Include="base\ntos\lpc\lpcinit.c" />
|
||||
<ClCompile Include="base\ntos\lpc\lpclistn.c" />
|
||||
<ClCompile Include="base\ntos\lpc\lpcpriv.c" />
|
||||
<ClCompile Include="base\ntos\lpc\lpcquery.c" />
|
||||
<ClCompile Include="base\ntos\lpc\lpcqueue.c" />
|
||||
<ClCompile Include="base\ntos\lpc\lpcrecv.c" />
|
||||
<ClCompile Include="base\ntos\lpc\lpcreply.c" />
|
||||
<ClCompile Include="base\ntos\lpc\lpcsend.c" />
|
||||
<ClCompile Include="base\ntos\mm\acceschk.c" />
|
||||
<ClCompile Include="base\ntos\mm\addrsup.c" />
|
||||
<ClCompile Include="base\ntos\mm\allocpag.c" />
|
||||
<ClCompile Include="base\ntos\mm\allocvm.c" />
|
||||
<ClCompile Include="base\ntos\mm\amd64\dataamd.c" />
|
||||
<ClCompile Include="base\ntos\mm\amd64\initamd.c" />
|
||||
<ClCompile Include="base\ntos\mm\buildmdl.c" />
|
||||
<ClCompile Include="base\ntos\mm\creasect.c" />
|
||||
<ClCompile Include="base\ntos\mm\deleteva.c" />
|
||||
<ClCompile Include="base\ntos\mm\dmpaddr.c" />
|
||||
<ClCompile Include="base\ntos\mm\extsect.c" />
|
||||
<ClCompile Include="base\ntos\mm\flushbuf.c" />
|
||||
<ClCompile Include="base\ntos\mm\flushsec.c" />
|
||||
<ClCompile Include="base\ntos\mm\forksup.c" />
|
||||
<ClCompile Include="base\ntos\mm\freevm.c" />
|
||||
<ClCompile Include="base\ntos\mm\hypermap.c" />
|
||||
<ClCompile Include="base\ntos\mm\i386\data386.c" />
|
||||
<ClCompile Include="base\ntos\mm\i386\init386.c" />
|
||||
<ClCompile Include="base\ntos\mm\i386\paesup.c" />
|
||||
<ClCompile Include="base\ntos\mm\i386\procpae.c" />
|
||||
<ClCompile Include="base\ntos\mm\i386\procx86.c" />
|
||||
<ClCompile Include="base\ntos\mm\i386\setmodfy.c" />
|
||||
<ClCompile Include="base\ntos\mm\iosup.c" />
|
||||
<ClCompile Include="base\ntos\mm\lockvm.c" />
|
||||
<ClCompile Include="base\ntos\mm\mapcache.c" />
|
||||
<ClCompile Include="base\ntos\mm\mapview.c" />
|
||||
<ClCompile Include="base\ntos\mm\miglobal.c" />
|
||||
<ClCompile Include="base\ntos\mm\mmfault.c" />
|
||||
<ClCompile Include="base\ntos\mm\mminit.c" />
|
||||
<ClCompile Include="base\ntos\mm\mmquota.c" />
|
||||
<ClCompile Include="base\ntos\mm\mmsup.c" />
|
||||
<ClCompile Include="base\ntos\mm\modwrite.c" />
|
||||
<ClCompile Include="base\ntos\mm\pagfault.c" />
|
||||
<ClCompile Include="base\ntos\mm\pfndec.c" />
|
||||
<ClCompile Include="base\ntos\mm\pfnlist.c" />
|
||||
<ClCompile Include="base\ntos\mm\physical.c" />
|
||||
<ClCompile Include="base\ntos\mm\procsup.c" />
|
||||
<ClCompile Include="base\ntos\mm\protect.c" />
|
||||
<ClCompile Include="base\ntos\mm\querysec.c" />
|
||||
<ClCompile Include="base\ntos\mm\queryvm.c" />
|
||||
<ClCompile Include="base\ntos\mm\readwrt.c" />
|
||||
<ClCompile Include="base\ntos\mm\sectsup.c" />
|
||||
<ClCompile Include="base\ntos\mm\session.c" />
|
||||
<ClCompile Include="base\ntos\mm\sessload.c" />
|
||||
<ClCompile Include="base\ntos\mm\shutdown.c" />
|
||||
<ClCompile Include="base\ntos\mm\sysload.c" />
|
||||
<ClCompile Include="base\ntos\mm\sysptes.c" />
|
||||
<ClCompile Include="base\ntos\mm\umapview.c" />
|
||||
<ClCompile Include="base\ntos\mm\vadtree.c" />
|
||||
<ClCompile Include="base\ntos\mm\wrtfault.c" />
|
||||
<ClCompile Include="base\ntos\mm\wrtwatch.c" />
|
||||
<ClCompile Include="base\ntos\mm\wslist.c" />
|
||||
<ClCompile Include="base\ntos\mm\wsmanage.c" />
|
||||
<ClCompile Include="base\ntos\mm\wstree.c" />
|
||||
<ClCompile Include="base\ntos\mm\zeropage.c" />
|
||||
<ClCompile Include="base\ntos\ob\fastref.c" />
|
||||
<ClCompile Include="base\ntos\ob\obclose.c" />
|
||||
<ClCompile Include="base\ntos\ob\obcreate.c" />
|
||||
<ClCompile Include="base\ntos\ob\obdevmap.c" />
|
||||
<ClCompile Include="base\ntos\ob\obdir.c" />
|
||||
<ClCompile Include="base\ntos\ob\obhandle.c" />
|
||||
<ClCompile Include="base\ntos\ob\obinit.c" />
|
||||
<ClCompile Include="base\ntos\ob\obinsert.c" />
|
||||
<ClCompile Include="base\ntos\ob\oblink.c" />
|
||||
<ClCompile Include="base\ntos\ob\obquery.c" />
|
||||
<ClCompile Include="base\ntos\ob\obref.c" />
|
||||
<ClCompile Include="base\ntos\ob\obsdata.c" />
|
||||
<ClCompile Include="base\ntos\ob\obse.c" />
|
||||
<ClCompile Include="base\ntos\ob\obtype.c" />
|
||||
<ClCompile Include="base\ntos\ob\obwait.c" />
|
||||
<ClCompile Include="base\ntos\perf\hooks.c" />
|
||||
<ClCompile Include="base\ntos\perf\logging.c" />
|
||||
<ClCompile Include="base\ntos\perf\perfdata.c" />
|
||||
<ClCompile Include="base\ntos\perf\perfsup.c" />
|
||||
<ClCompile Include="base\ntos\ps\amd64\psctxamd64.c" />
|
||||
<ClCompile Include="base\ntos\ps\amd64\psldt.c" />
|
||||
<ClCompile Include="base\ntos\ps\amd64\psvdm.c" />
|
||||
<ClCompile Include="base\ntos\ps\create.c" />
|
||||
<ClCompile Include="base\ntos\ps\i386\psctx386.c" />
|
||||
<ClCompile Include="base\ntos\ps\i386\psldt.c" />
|
||||
<ClCompile Include="base\ntos\ps\i386\psvdm.c" />
|
||||
<ClCompile Include="base\ntos\ps\kulookup.c" />
|
||||
<ClCompile Include="base\ntos\ps\pscid.c" />
|
||||
<ClCompile Include="base\ntos\ps\psctx.c" />
|
||||
<ClCompile Include="base\ntos\ps\psdelete.c" />
|
||||
<ClCompile Include="base\ntos\ps\psenum.c" />
|
||||
<ClCompile Include="base\ntos\ps\pshelper.c" />
|
||||
<ClCompile Include="base\ntos\ps\psimpers.c" />
|
||||
<ClCompile Include="base\ntos\ps\psinit.c" />
|
||||
<ClCompile Include="base\ntos\ps\psjob.c" />
|
||||
<ClCompile Include="base\ntos\ps\psopen.c" />
|
||||
<ClCompile Include="base\ntos\ps\psquery.c" />
|
||||
<ClCompile Include="base\ntos\ps\psquota.c" />
|
||||
<ClCompile Include="base\ntos\ps\psspnd.c" />
|
||||
<ClCompile Include="base\ntos\ps\security.c" />
|
||||
<ClCompile Include="base\ntos\raw\cleanup.c" />
|
||||
<ClCompile Include="base\ntos\raw\close.c" />
|
||||
<ClCompile Include="base\ntos\raw\create.c" />
|
||||
<ClCompile Include="base\ntos\raw\fileinfo.c" />
|
||||
<ClCompile Include="base\ntos\raw\fsctrl.c" />
|
||||
<ClCompile Include="base\ntos\raw\rawdisp.c" />
|
||||
<ClCompile Include="base\ntos\raw\rawinit.c" />
|
||||
<ClCompile Include="base\ntos\raw\readwrit.c" />
|
||||
<ClCompile Include="base\ntos\raw\strucsup.c" />
|
||||
<ClCompile Include="base\ntos\rtl\acledit.c" />
|
||||
<ClCompile Include="base\ntos\rtl\add2stra.c" />
|
||||
<ClCompile Include="base\ntos\rtl\add2strw.c" />
|
||||
<ClCompile Include="base\ntos\rtl\amd64\context.c" />
|
||||
<ClCompile Include="base\ntos\rtl\amd64\exdsptch.c" />
|
||||
<ClCompile Include="base\ntos\rtl\amd64\misalign.c" />
|
||||
<ClCompile Include="base\ntos\rtl\amd64\raise.c" />
|
||||
<ClCompile Include="base\ntos\rtl\amd64\stkwalk.c" />
|
||||
<ClCompile Include="base\ntos\rtl\assert.c" />
|
||||
<ClCompile Include="base\ntos\rtl\atom.c" />
|
||||
<ClCompile Include="base\ntos\rtl\avltable.c" />
|
||||
<ClCompile Include="base\ntos\rtl\bitmap.c" />
|
||||
<ClCompile Include="base\ntos\rtl\byteswap.c" />
|
||||
<ClCompile Include="base\ntos\rtl\cnvint.c" />
|
||||
<ClCompile Include="base\ntos\rtl\debug.c" />
|
||||
<ClCompile Include="base\ntos\rtl\eballoc.c" />
|
||||
<ClCompile Include="base\ntos\rtl\environ.c" />
|
||||
<ClCompile Include="base\ntos\rtl\error.c" />
|
||||
<ClCompile Include="base\ntos\rtl\excptdbg.c" />
|
||||
<ClCompile Include="base\ntos\rtl\generr.c" />
|
||||
<ClCompile Include="base\ntos\rtl\gentable.c" />
|
||||
<ClCompile Include="base\ntos\rtl\guid.c" />
|
||||
<ClCompile Include="base\ntos\rtl\i386\context.c" />
|
||||
<ClCompile Include="base\ntos\rtl\i386\debug3.c" />
|
||||
<ClCompile Include="base\ntos\rtl\i386\divlarge.c" />
|
||||
<ClCompile Include="base\ntos\rtl\i386\exdsptch.c" />
|
||||
<ClCompile Include="base\ntos\rtl\i386\getcalr.c" />
|
||||
<ClCompile Include="base\ntos\rtl\imagedir.c" />
|
||||
<ClCompile Include="base\ntos\rtl\intbits.c" />
|
||||
<ClCompile Include="base\ntos\rtl\ldrreloc.c" />
|
||||
<ClCompile Include="base\ntos\rtl\ldrrsrc.c" />
|
||||
<ClCompile Include="base\ntos\rtl\lookup.c" />
|
||||
<ClCompile Include="base\ntos\rtl\message.c" />
|
||||
<ClCompile Include="base\ntos\rtl\nls.c" />
|
||||
<ClCompile Include="base\ntos\rtl\nlsxlat.c" />
|
||||
<ClCompile Include="base\ntos\rtl\pctohdr.c" />
|
||||
<ClCompile Include="base\ntos\rtl\peb.c" />
|
||||
<ClCompile Include="base\ntos\rtl\prefix.c" />
|
||||
<ClCompile Include="base\ntos\rtl\regutil.c" />
|
||||
<ClCompile Include="base\ntos\rtl\rtlassig.c" />
|
||||
<ClCompile Include="base\ntos\rtl\rtldata.c" />
|
||||
<ClCompile Include="base\ntos\rtl\rtlexec.c" />
|
||||
<ClCompile Include="base\ntos\rtl\rtlnthdr.c" />
|
||||
<ClCompile Include="base\ntos\rtl\sertl.c" />
|
||||
<ClCompile Include="base\ntos\rtl\splay.c" />
|
||||
<ClCompile Include="base\ntos\rtl\stktrace.c" />
|
||||
<ClCompile Include="base\ntos\rtl\str2adda.c" />
|
||||
<ClCompile Include="base\ntos\rtl\str2addw.c" />
|
||||
<ClCompile Include="base\ntos\rtl\string.c" />
|
||||
<ClCompile Include="base\ntos\rtl\sysvol.c" />
|
||||
<ClCompile Include="base\ntos\rtl\time.c" />
|
||||
<ClCompile Include="base\ntos\rtl\tracedb.c" />
|
||||
<ClCompile Include="base\ntos\se\accessck.c" />
|
||||
<ClCompile Include="base\ntos\se\adtinit.c" />
|
||||
<ClCompile Include="base\ntos\se\adtlog.c" />
|
||||
<ClCompile Include="base\ntos\se\adtutil.c" />
|
||||
<ClCompile Include="base\ntos\se\adtvars.c" />
|
||||
<ClCompile Include="base\ntos\se\capture.c" />
|
||||
<ClCompile Include="base\ntos\se\privileg.c" />
|
||||
<ClCompile Include="base\ntos\se\rmaudit.c" />
|
||||
<ClCompile Include="base\ntos\se\rmlogon.c" />
|
||||
<ClCompile Include="base\ntos\se\rmmain.c" />
|
||||
<ClCompile Include="base\ntos\se\rmvars.c" />
|
||||
<ClCompile Include="base\ntos\se\seassign.c" />
|
||||
<ClCompile Include="base\ntos\se\seastate.c" />
|
||||
<ClCompile Include="base\ntos\se\seaudit.c" />
|
||||
<ClCompile Include="base\ntos\se\seclient.c" />
|
||||
<ClCompile Include="base\ntos\se\seglobal.c" />
|
||||
<ClCompile Include="base\ntos\se\seinit.c" />
|
||||
<ClCompile Include="base\ntos\se\semethod.c" />
|
||||
<ClCompile Include="base\ntos\se\sep.c" />
|
||||
<ClCompile Include="base\ntos\se\sepaudit.c" />
|
||||
<ClCompile Include="base\ntos\se\subject.c" />
|
||||
<ClCompile Include="base\ntos\se\token.c" />
|
||||
<ClCompile Include="base\ntos\se\tokenadj.c" />
|
||||
<ClCompile Include="base\ntos\se\tokendup.c" />
|
||||
<ClCompile Include="base\ntos\se\tokenopn.c" />
|
||||
<ClCompile Include="base\ntos\se\tokenqry.c" />
|
||||
<ClCompile Include="base\ntos\se\tokenset.c" />
|
||||
<ClCompile Include="base\ntos\wmi\alloc.c" />
|
||||
<ClCompile Include="base\ntos\wmi\amd64\mcaevent.c" />
|
||||
<ClCompile Include="base\ntos\wmi\api.c" />
|
||||
<ClCompile Include="base\ntos\wmi\callouts.c" />
|
||||
<ClCompile Include="base\ntos\wmi\chunk.c" />
|
||||
<ClCompile Include="base\ntos\wmi\consumer.c" />
|
||||
<ClCompile Include="base\ntos\wmi\dataprov.c" />
|
||||
<ClCompile Include="base\ntos\wmi\ds.c" />
|
||||
<ClCompile Include="base\ntos\wmi\enabdisa.c" />
|
||||
<ClCompile Include="base\ntos\wmi\globalog.c" />
|
||||
<ClCompile Include="base\ntos\wmi\i386\mcaevent.c" />
|
||||
<ClCompile Include="base\ntos\wmi\mca.c" />
|
||||
<ClCompile Include="base\ntos\wmi\notify.c" />
|
||||
<ClCompile Include="base\ntos\wmi\provider.c" />
|
||||
<ClCompile Include="base\ntos\wmi\register.c" />
|
||||
<ClCompile Include="base\ntos\wmi\secure.c" />
|
||||
<ClCompile Include="base\ntos\wmi\smbios.c" />
|
||||
<ClCompile Include="base\ntos\wmi\traceapi.c" />
|
||||
<ClCompile Include="base\ntos\wmi\tracelog.c" />
|
||||
<ClCompile Include="base\ntos\wmi\tracesup.c" />
|
||||
<ClCompile Include="base\ntos\wmi\wmi.c" />
|
||||
<ClCompile Include="base\ntos\wmi\wmidata.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="base\inc\ntdlltrc.h" />
|
||||
<ClInclude Include="base\ntos\cache\cc.h" />
|
||||
<ClInclude Include="base\ntos\config\cmp.h" />
|
||||
<ClInclude Include="base\ntos\config\cmpbug.h" />
|
||||
<ClInclude Include="base\ntos\config\hive.h" />
|
||||
<ClInclude Include="base\ntos\dbgk\dbgkp.h" />
|
||||
<ClInclude Include="base\ntos\ex\exp.h" />
|
||||
<ClInclude Include="base\ntos\fsrtl\fsrtlp.h" />
|
||||
<ClInclude Include="base\ntos\fstub\drivesup.h" />
|
||||
<ClInclude Include="base\ntos\fstub\fstub.h" />
|
||||
<ClInclude Include="base\ntos\fstub\haldisp.h" />
|
||||
<ClInclude Include="base\ntos\inc\amd64.h" />
|
||||
<ClInclude Include="base\ntos\inc\cache.h" />
|
||||
<ClInclude Include="base\ntos\inc\cm.h" />
|
||||
<ClInclude Include="base\ntos\inc\cmdata.h" />
|
||||
<ClInclude Include="base\ntos\inc\cpyuchr.h" />
|
||||
<ClInclude Include="base\ntos\inc\dbgk.h" />
|
||||
<ClInclude Include="base\ntos\inc\dockintf.h" />
|
||||
<ClInclude Include="base\ntos\inc\ex.h" />
|
||||
<ClInclude Include="base\ntos\inc\exboosts.h" />
|
||||
<ClInclude Include="base\ntos\inc\exlevels.h" />
|
||||
<ClInclude Include="base\ntos\inc\fsrtl.h" />
|
||||
<ClInclude Include="base\ntos\inc\hal.h" />
|
||||
<ClInclude Include="base\ntos\inc\hivedata.h" />
|
||||
<ClInclude Include="base\ntos\inc\i386.h" />
|
||||
<ClInclude Include="base\ntos\inc\init.h" />
|
||||
<ClInclude Include="base\ntos\inc\intrlk.h" />
|
||||
<ClInclude Include="base\ntos\inc\io.h" />
|
||||
<ClInclude Include="base\ntos\inc\kd.h" />
|
||||
<ClInclude Include="base\ntos\inc\kddll.h" />
|
||||
<ClInclude Include="base\ntos\inc\ke.h" />
|
||||
<ClInclude Include="base\ntos\inc\kx.h" />
|
||||
<ClInclude Include="base\ntos\inc\lfs.h" />
|
||||
<ClInclude Include="base\ntos\inc\lpc.h" />
|
||||
<ClInclude Include="base\ntos\inc\mm.h" />
|
||||
<ClInclude Include="base\ntos\inc\ntos.h" />
|
||||
<ClInclude Include="base\ntos\inc\ntosdef.h" />
|
||||
<ClInclude Include="base\ntos\inc\ob.h" />
|
||||
<ClInclude Include="base\ntos\inc\perf.h" />
|
||||
<ClInclude Include="base\ntos\inc\pnp.h" />
|
||||
<ClInclude Include="base\ntos\inc\po.h" />
|
||||
<ClInclude Include="base\ntos\inc\pool.h" />
|
||||
<ClInclude Include="base\ntos\inc\procpowr.h" />
|
||||
<ClInclude Include="base\ntos\inc\ps.h" />
|
||||
<ClInclude Include="base\ntos\inc\se.h" />
|
||||
<ClInclude Include="base\ntos\inc\smbios.h" />
|
||||
<ClInclude Include="base\ntos\inc\stktrace.h" />
|
||||
<ClInclude Include="base\ntos\inc\v86emul.h" />
|
||||
<ClInclude Include="base\ntos\inc\vdmntos.h" />
|
||||
<ClInclude Include="base\ntos\inc\verifier.h" />
|
||||
<ClInclude Include="base\ntos\inc\wmi.h" />
|
||||
<ClInclude Include="base\ntos\io\iomgr\iomgr.h" />
|
||||
<ClInclude Include="base\ntos\io\iop.h" />
|
||||
<ClInclude Include="base\ntos\io\iopcmn.h" />
|
||||
<ClInclude Include="base\ntos\io\ioverifier.h" />
|
||||
<ClInclude Include="base\ntos\io\iovutil.h" />
|
||||
<ClInclude Include="base\ntos\io\PNPMGR\pplastgood.h" />
|
||||
<ClInclude Include="base\ntos\io\PNPMGR\ppvutil.h" />
|
||||
<ClInclude Include="base\ntos\io\sessnirp.h" />
|
||||
<ClInclude Include="base\ntos\io\trackirp.h" />
|
||||
<ClInclude Include="base\ntos\ke\amd64\kiamd64.h" />
|
||||
<ClInclude Include="base\ntos\ke\i386\abios.h" />
|
||||
<ClInclude Include="base\ntos\ke\i386\kix86.h" />
|
||||
<ClInclude Include="base\ntos\ke\i386\mtrr.h" />
|
||||
<ClInclude Include="base\ntos\ke\i386\pat.h" />
|
||||
<ClInclude Include="base\ntos\ke\ki.h" />
|
||||
<ClInclude Include="base\ntos\lpc\lpcp.h" />
|
||||
<ClInclude Include="base\ntos\mm\amd64\miamd.h" />
|
||||
<ClInclude Include="base\ntos\mm\i386\mi386.h" />
|
||||
<ClInclude Include="base\ntos\mm\mi.h" />
|
||||
<ClInclude Include="base\ntos\ob\obp.h" />
|
||||
<ClInclude Include="base\ntos\ob\obvutil.h" />
|
||||
<ClInclude Include="base\ntos\perf\perfp.h" />
|
||||
<ClInclude Include="base\ntos\ps\psp.h" />
|
||||
<ClInclude Include="base\ntos\raw\nodetype.h" />
|
||||
<ClInclude Include="base\ntos\raw\rawprocs.h" />
|
||||
<ClInclude Include="base\ntos\raw\rawstruc.h" />
|
||||
<ClInclude Include="base\ntos\rtl\add2strt.h" />
|
||||
<ClInclude Include="base\ntos\rtl\amd64\ntrtlamd64.h" />
|
||||
<ClInclude Include="base\ntos\rtl\error.h" />
|
||||
<ClInclude Include="base\ntos\rtl\i386\ntrtl386.h" />
|
||||
<ClInclude Include="base\ntos\rtl\ntrtlp.h" />
|
||||
<ClInclude Include="base\ntos\rtl\str2addt.h" />
|
||||
<ClInclude Include="base\ntos\rtl\tracedbp.h" />
|
||||
<ClInclude Include="base\ntos\se\adt.h" />
|
||||
<ClInclude Include="base\ntos\se\adtp.h" />
|
||||
<ClInclude Include="base\ntos\se\adtutil.h" />
|
||||
<ClInclude Include="base\ntos\se\pch.h" />
|
||||
<ClInclude Include="base\ntos\se\rmp.h" />
|
||||
<ClInclude Include="base\ntos\se\sep.h" />
|
||||
<ClInclude Include="base\ntos\se\tokenp.h" />
|
||||
<ClInclude Include="base\ntos\VERIFIER\halverifier.h" />
|
||||
<ClInclude Include="base\ntos\VERIFIER\vfbugcheck.h" />
|
||||
<ClInclude Include="base\ntos\VERIFIER\vfddi.h" />
|
||||
<ClInclude Include="base\ntos\VERIFIER\vfdeadlock.h" />
|
||||
<ClInclude Include="base\ntos\VERIFIER\vfdebug.h" />
|
||||
<ClInclude Include="base\ntos\VERIFIER\vfdef.h" />
|
||||
<ClInclude Include="base\ntos\VERIFIER\vfdevobj.h" />
|
||||
<ClInclude Include="base\ntos\VERIFIER\vffilter.h" />
|
||||
<ClInclude Include="base\ntos\VERIFIER\vfgeneric.h" />
|
||||
<ClInclude Include="base\ntos\VERIFIER\vfinit.h" />
|
||||
<ClInclude Include="base\ntos\VERIFIER\vfirp.h" />
|
||||
<ClInclude Include="base\ntos\VERIFIER\vfirpdb.h" />
|
||||
<ClInclude Include="base\ntos\VERIFIER\vfirplog.h" />
|
||||
<ClInclude Include="base\ntos\VERIFIER\vfmacro.h" />
|
||||
<ClInclude Include="base\ntos\VERIFIER\vfmajor.h" />
|
||||
<ClInclude Include="base\ntos\VERIFIER\vfmessage.h" />
|
||||
<ClInclude Include="base\ntos\VERIFIER\vfpacket.h" />
|
||||
<ClInclude Include="base\ntos\VERIFIER\vfpnp.h" />
|
||||
<ClInclude Include="base\ntos\VERIFIER\vfpower.h" />
|
||||
<ClInclude Include="base\ntos\VERIFIER\vfpragma.h" />
|
||||
<ClInclude Include="base\ntos\VERIFIER\vfprint.h" />
|
||||
<ClInclude Include="base\ntos\VERIFIER\vfrandom.h" />
|
||||
<ClInclude Include="base\ntos\VERIFIER\vfsettings.h" />
|
||||
<ClInclude Include="base\ntos\VERIFIER\vfstack.h" />
|
||||
<ClInclude Include="base\ntos\VERIFIER\vftriage.h" />
|
||||
<ClInclude Include="base\ntos\VERIFIER\vfutil.h" />
|
||||
<ClInclude Include="base\ntos\VERIFIER\vfwmi.h" />
|
||||
<ClInclude Include="base\ntos\VERIFIER\vfzwapi.h" />
|
||||
<ClInclude Include="base\ntos\wmi\mcaevent.h" />
|
||||
<ClInclude Include="base\ntos\wmi\tracep.h" />
|
||||
<ClInclude Include="base\ntos\wmi\wmikmp.h" />
|
||||
<ClInclude Include="base\ntos\wmi\wmiumds.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="base\ntos\ex\amd64\hifreqlk.asm" />
|
||||
<None Include="base\ntos\ex\amd64\hrderror.asm" />
|
||||
<None Include="base\ntos\ex\amd64\intrlock.asm" />
|
||||
<None Include="base\ntos\ex\i386\intrlfst.asm" />
|
||||
<None Include="base\ntos\ex\i386\intrlock.asm" />
|
||||
<None Include="base\ntos\ex\i386\splocks.asm" />
|
||||
<None Include="base\ntos\inc\em387.inc" />
|
||||
<None Include="base\ntos\inc\fastsys.inc" />
|
||||
<None Include="base\ntos\inc\irqli386.inc" />
|
||||
<None Include="base\ntos\inc\mac386.inc" />
|
||||
<None Include="base\ntos\init\amd64def.src" />
|
||||
<None Include="base\ntos\init\i386def.src" />
|
||||
<None Include="base\ntos\init\ntoskrnl.src" />
|
||||
<None Include="base\ntos\ke\amd64\apcint.asm" />
|
||||
<None Include="base\ntos\ke\amd64\callout.asm" />
|
||||
<None Include="base\ntos\ke\amd64\clockint.asm" />
|
||||
<None Include="base\ntos\ke\amd64\cpuid.asm" />
|
||||
<None Include="base\ntos\ke\amd64\ctxswap.asm" />
|
||||
<None Include="base\ntos\ke\amd64\dpcint.asm" />
|
||||
<None Include="base\ntos\ke\amd64\idle.asm" />
|
||||
<None Include="base\ntos\ke\amd64\intipi.asm" />
|
||||
<None Include="base\ntos\ke\amd64\intsup.asm" />
|
||||
<None Include="base\ntos\ke\amd64\miscs.asm" />
|
||||
<None Include="base\ntos\ke\amd64\procstat.asm" />
|
||||
<None Include="base\ntos\ke\amd64\profint.asm" />
|
||||
<None Include="base\ntos\ke\amd64\services.stb" />
|
||||
<None Include="base\ntos\ke\amd64\services.tab" />
|
||||
<None Include="base\ntos\ke\amd64\start.asm" />
|
||||
<None Include="base\ntos\ke\amd64\sysstubs.asm" />
|
||||
<None Include="base\ntos\ke\amd64\systable.asm" />
|
||||
<None Include="base\ntos\ke\amd64\table.stb" />
|
||||
<None Include="base\ntos\ke\amd64\threadbg.asm" />
|
||||
<None Include="base\ntos\ke\amd64\trap.asm" />
|
||||
<None Include="base\ntos\ke\amd64\zero.asm" />
|
||||
<None Include="base\ntos\ke\genxx.inc" />
|
||||
<None Include="base\ntos\ke\i386\abiosa.asm" />
|
||||
<None Include="base\ntos\ke\i386\callout.asm" />
|
||||
<None Include="base\ntos\ke\i386\clockint.asm" />
|
||||
<None Include="base\ntos\ke\i386\cpu.asm" />
|
||||
<None Include="base\ntos\ke\i386\cpu.inc" />
|
||||
<None Include="base\ntos\ke\i386\ctxswap.asm" />
|
||||
<None Include="base\ntos\ke\i386\emv86.asm" />
|
||||
<None Include="base\ntos\ke\i386\emxcptn.asm" />
|
||||
<None Include="base\ntos\ke\i386\i386pcr.asm" />
|
||||
<None Include="base\ntos\ke\i386\instemul.asm" />
|
||||
<None Include="base\ntos\ke\i386\int.asm" />
|
||||
<None Include="base\ntos\ke\i386\intsup.asm" />
|
||||
<None Include="base\ntos\ke\i386\kimacro.inc" />
|
||||
<None Include="base\ntos\ke\i386\ldtsup2.asm" />
|
||||
<None Include="base\ntos\ke\i386\mi.inc" />
|
||||
<None Include="base\ntos\ke\i386\mpipia.asm" />
|
||||
<None Include="base\ntos\ke\i386\newsysbg.asm" />
|
||||
<None Include="base\ntos\ke\i386\procstat.asm" />
|
||||
<None Include="base\ntos\ke\i386\services.stb" />
|
||||
<None Include="base\ntos\ke\i386\services.tab" />
|
||||
<None Include="base\ntos\ke\i386\spindbg.asm" />
|
||||
<None Include="base\ntos\ke\i386\spinlock.asm" />
|
||||
<None Include="base\ntos\ke\i386\sysstubs.asm" />
|
||||
<None Include="base\ntos\ke\i386\systable.asm" />
|
||||
<None Include="base\ntos\ke\i386\table.stb" />
|
||||
<None Include="base\ntos\ke\i386\threadbg.asm" />
|
||||
<None Include="base\ntos\ke\i386\timindex.asm" />
|
||||
<None Include="base\ntos\ke\i386\trap.asm" />
|
||||
<None Include="base\ntos\ke\i386\zero.asm" />
|
||||
<None Include="base\ntos\lpc\i386\lpcmove.asm" />
|
||||
<None Include="base\ntos\mm\i386\pae.asm" />
|
||||
<None Include="base\ntos\ps\amd64\psctxwrap.asm" />
|
||||
<None Include="base\ntos\rtl\amd64\capture.asm" />
|
||||
<None Include="base\ntos\rtl\amd64\chkstk.asm" />
|
||||
<None Include="base\ntos\rtl\amd64\debugstb.asm" />
|
||||
<None Include="base\ntos\rtl\amd64\movemem.asm" />
|
||||
<None Include="base\ntos\rtl\amd64\slist.asm" />
|
||||
<None Include="base\ntos\rtl\amd64\xcptmisc.asm" />
|
||||
<None Include="base\ntos\rtl\i386\debug2.asm" />
|
||||
<None Include="base\ntos\rtl\i386\ioaccess.asm" />
|
||||
<None Include="base\ntos\rtl\i386\largeint.asm" />
|
||||
<None Include="base\ntos\rtl\i386\movemem.asm" />
|
||||
<None Include="base\ntos\rtl\i386\raise.asm" />
|
||||
<None Include="base\ntos\rtl\i386\slist.asm" />
|
||||
<None Include="base\ntos\rtl\i386\stkwalk.asm" />
|
||||
<None Include="base\ntos\rtl\i386\stringsp.asm" />
|
||||
<None Include="base\ntos\rtl\i386\xcptmisc.asm" />
|
||||
<None Include="base\ntos\rtl\mp" />
|
||||
<None Include="base\ntos\VDM\i386\vdm.inc" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
2039
WRK.vcxproj.filters
Normal file
2039
WRK.vcxproj.filters
Normal file
File diff suppressed because it is too large
Load Diff
3
WRKDebug.bat
Normal file
3
WRKDebug.bat
Normal file
@ -0,0 +1,3 @@
|
||||
call WRKEnv.bat %1
|
||||
windbg %windbgargs%
|
||||
|
||||
24
WRKEnv.bat
Normal file
24
WRKEnv.bat
Normal file
@ -0,0 +1,24 @@
|
||||
@echo off
|
||||
rem
|
||||
rem This batch file sets the following WRK build and debug environment variables:
|
||||
rem wrkarch - the target architecture, "x86" or "amd64"; 1st parameter of the batch file; default is x86
|
||||
rem path - the search path, modified to include the tools for respective target architecture
|
||||
rem and Windows Debugger (WinDbg)
|
||||
rem windbgargs - the arguments for WinDbg
|
||||
rem _NT_SYMBOL_PATH - symbol path for WinDbg
|
||||
rem
|
||||
rem Usage: copy this file to your hard drive and edit it to reflect your installation;
|
||||
rem open a console window and run this batch file;
|
||||
rem run command "set" to make sure the environment is set properly;
|
||||
rem now you can build WRK and run Windbg from this console window.
|
||||
rem
|
||||
IF DEFINED wrkarch goto finish
|
||||
SET wrkarch=x86
|
||||
IF NOT [%1] EQU [] SET wrkarch=%1
|
||||
SET path=%cd%\tools\%wrkarch%;%path%;C:\Program Files\Debugging Tools for Windows
|
||||
SET windbgargs=-k com:pipe,port=\\.\pipe\debug,resets=0,reconnect
|
||||
SET _NT_SYMBOL_PATH="%cd%\base\ntos\build\exe;%cd%\WS03SP1HALS\x86\halacpim"
|
||||
@title WRK %wrkarch%
|
||||
:finish
|
||||
|
||||
|
||||
BIN
WS03SP1HALS/x86/halacpim/halacpim.dll
Normal file
BIN
WS03SP1HALS/x86/halacpim/halacpim.dll
Normal file
Binary file not shown.
BIN
WS03SP1HALS/x86/halacpim/halacpim.pdb
Normal file
BIN
WS03SP1HALS/x86/halacpim/halacpim.pdb
Normal file
Binary file not shown.
BIN
WS03SP1HALS/x86/halmacpi/halmacpi.dll
Normal file
BIN
WS03SP1HALS/x86/halmacpi/halmacpi.dll
Normal file
Binary file not shown.
BIN
WS03SP1HALS/x86/halmacpi/halmacpi.pdb
Normal file
BIN
WS03SP1HALS/x86/halmacpi/halmacpi.pdb
Normal file
Binary file not shown.
BIN
WS03SP1HALS/x86/halmps/halmps.dll
Normal file
BIN
WS03SP1HALS/x86/halmps/halmps.dll
Normal file
Binary file not shown.
BIN
WS03SP1HALS/x86/halmps/halmps.pdb
Normal file
BIN
WS03SP1HALS/x86/halmps/halmps.pdb
Normal file
Binary file not shown.
109
base/inc/ntdlltrc.h
Normal file
109
base/inc/ntdlltrc.h
Normal file
@ -0,0 +1,109 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 1997-2000 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
NtdllTracer.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This file contains structures and functions definitions used in Ntdll
|
||||
events tracing
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef _NTDLL_WMI_TRACE_
|
||||
#define _NTDLL_WMI_TRACE_
|
||||
|
||||
#define MEMORY_FROM_LOOKASIDE 1 //Activity from LookAside
|
||||
#define MEMORY_FROM_LOWFRAG 2 //Activity from Low Frag Heap
|
||||
#define MEMORY_FROM_MAINPATH 3 //Activity from Main Code Path
|
||||
#define MEMORY_FROM_SLOWPATH 4 //Activity from Slow Code Path
|
||||
|
||||
#define LOG_LOOKASIDE 0x00000001 //Bit for LookAside trace
|
||||
|
||||
#define FAILED_TLSINDEX -1
|
||||
#define MAX_PID 10
|
||||
|
||||
#ifndef UserSharedData
|
||||
#define UserSharedData USER_SHARED_DATA
|
||||
#endif
|
||||
|
||||
#define IN_TRACING 0x00000001 // Flag to see if this thread is tracing.
|
||||
extern BOOLEAN bNtdllTrace;
|
||||
|
||||
#define IsCritSecLogging(CriticalSection) ((USER_SHARED_DATA->TraceLogging & ENABLECRITSECTRACE) \
|
||||
&&(bNtdllTrace || GlobalCounter != (USER_SHARED_DATA->TraceLogging >> 16)) \
|
||||
&&((HandleToUlong(NtCurrentTeb()->EtwTraceData) & IN_TRACING) != IN_TRACING))
|
||||
|
||||
extern
|
||||
ULONG GlobalCounter;
|
||||
|
||||
#define IsHeapLogging(HeapHandle) (USER_SHARED_DATA->TraceLogging & ENABLEHEAPTRACE &&\
|
||||
(bNtdllTrace || GlobalCounter != (USER_SHARED_DATA->TraceLogging >> 16))&& \
|
||||
((HandleToUlong(NtCurrentTeb()->EtwTraceData) & IN_TRACING) != IN_TRACING))
|
||||
|
||||
//
|
||||
// When calling from deep inside heap allocation routines, we do not want to
|
||||
// be initializing ETW process heap since that gets into recursive behaviour.
|
||||
//
|
||||
|
||||
#define IsDeepHeapLogging(HeapHandle) (USER_SHARED_DATA->TraceLogging & ENABLEHEAPTRACE &&\
|
||||
(bNtdllTrace || GlobalCounter != (USER_SHARED_DATA->TraceLogging >> 16))&& \
|
||||
(EtwpProcessHeap != NULL) && \
|
||||
((HandleToUlong(NtCurrentTeb()->EtwTraceData) & IN_TRACING) != IN_TRACING))
|
||||
|
||||
|
||||
typedef struct _THREAD_LOCAL_DATA THREAD_LOCAL_DATA, *PTHREAD_LOCAL_DATA, **PPTHREAD_LOCAL_DATA;
|
||||
|
||||
typedef struct _THREAD_LOCAL_DATA {
|
||||
|
||||
PTHREAD_LOCAL_DATA FLink; //Forward Link
|
||||
PTHREAD_LOCAL_DATA BLink; //Backward Link
|
||||
PWMI_BUFFER_HEADER pBuffer; //Pointer to thread buffer info.
|
||||
LONG ReferenceCount;
|
||||
|
||||
} THREAD_LOCAL_DATA, *PTHREAD_LOCAL_DATA, **PPTHREAD_LOCAL_DATA;
|
||||
|
||||
extern
|
||||
PVOID EtwpProcessHeap;
|
||||
|
||||
#ifndef EtwpGetCycleCount
|
||||
|
||||
__int64
|
||||
EtwpGetCycleCount();
|
||||
|
||||
#endif // EtwpGetCycleCount
|
||||
|
||||
void
|
||||
ReleaseBufferLocation(PTHREAD_LOCAL_DATA pThreadLocalData);
|
||||
|
||||
NTSTATUS
|
||||
AcquireBufferLocation(PVOID *pEvent, PPTHREAD_LOCAL_DATA pThreadLocalData, PUSHORT ReqSize);
|
||||
|
||||
typedef struct _NTDLL_EVENT_COMMON {
|
||||
|
||||
PVOID Handle; //Handle of Heap
|
||||
|
||||
}NTDLL_EVENT_COMMON, *PNTDLL_EVENT_COMMON;
|
||||
|
||||
|
||||
typedef struct _NTDLL_EVENT_HANDLES {
|
||||
|
||||
RTL_CRITICAL_SECTION CriticalSection; //Critical section
|
||||
ULONG dwTlsIndex; //TLS Index
|
||||
TRACEHANDLE hRegistrationHandle; //Registration Handle used for Unregistration.
|
||||
TRACEHANDLE hLoggerHandle; //Handle to Trace Logger
|
||||
PTHREAD_LOCAL_DATA pThreadListHead; //Link List that contains all threads info invovled in tracing.
|
||||
|
||||
}NTDLL_EVENT_HANDLES, *PNTDLL_EVENT_HANDLES, **PPNTDLL_EVENT_HANDLES;
|
||||
|
||||
extern LONG TraceLevel;
|
||||
extern PNTDLL_EVENT_HANDLES NtdllTraceHandles;
|
||||
extern RTL_CRITICAL_SECTION UMLogCritSect;
|
||||
extern RTL_CRITICAL_SECTION PMCritSect;
|
||||
extern RTL_CRITICAL_SECTION LoaderLock;
|
||||
|
||||
#endif //_NTDLL_WMI_TRACE_
|
||||
1
base/ntos/BUILD/EXE/Placeholder.txt
Normal file
1
base/ntos/BUILD/EXE/Placeholder.txt
Normal file
@ -0,0 +1 @@
|
||||
*** This file is here solely to preserve the directory structure when WRK is xcopy'ed ***
|
||||
76
base/ntos/BUILD/WARNING.h
Normal file
76
base/ntos/BUILD/WARNING.h
Normal file
@ -0,0 +1,76 @@
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
// If you do not agree to the terms, do not use the code.
|
||||
//
|
||||
|
||||
#pragma warning(3:4092) // sizeof returns 'unsigned long'
|
||||
#pragma warning(4:4096) // '__cdecl' must be used with '...'
|
||||
#pragma warning(4:4121) // structure is sensitive to alignment
|
||||
#pragma warning(3:4125) // decimal digit in octal sequence
|
||||
#pragma warning(3:4130) // logical operation on address of string constant
|
||||
#pragma warning(3:4132) // const object should be initialized
|
||||
#if _DBG_MEMCPY_INLINE_
|
||||
#pragma warning(disable:4163) // not available as an intrinsic function
|
||||
#endif
|
||||
#pragma warning(4:4206) // Source File is empty
|
||||
#pragma warning(4:4101) // Unreferenced local variable
|
||||
#pragma warning(4:4208) // delete[exp] - exp evaluated but ignored
|
||||
#pragma warning(3:4212) // function declaration used ellipsis
|
||||
#pragma warning(3:4242) // convertion possible loss of data
|
||||
#pragma warning(4:4267) // convertion from size_t to smaller type
|
||||
#pragma warning(4:4312) // conversion to type of greater size
|
||||
#pragma warning(disable:4324) // structure padded due to __declspec(align())
|
||||
#pragma warning(error:4700) // Local used w/o being initialized
|
||||
#pragma warning(error:4259) // pure virtual function was not defined
|
||||
#pragma warning(disable:4071) // no function prototype given - formals unspecified
|
||||
#pragma warning(error:4013) // function' undefined - assuming extern returning int
|
||||
#pragma warning(error:4551) // Function call missing argument list
|
||||
#pragma warning(error:4806) // unsafe operation involving type 'bool'
|
||||
#pragma warning(4:4509) // use of SEH with destructor
|
||||
#pragma warning(4:4177) // pragma data_seg s/b at global scope
|
||||
#pragma warning(disable:4274) // #ident ignored
|
||||
#pragma warning(disable:4786) // identifier was truncated to 255 characters in debug information.
|
||||
#pragma warning(disable:4503) // decorated name length exceeded, name was truncated.
|
||||
#pragma warning(disable:4263) // Derived override doesn't match base - who cares...
|
||||
#pragma warning(disable:4264) // base function is hidden - again who cares.
|
||||
#pragma warning(disable:4710) // Function marked as inline - wasn't
|
||||
#pragma warning(disable:4917) // A GUID can only be associated with a class, interface or namespace
|
||||
#pragma warning(error:4552) // <<, >> ops used to no effect (probably missing an = sign)
|
||||
#pragma warning(error:4553) // == op used w/o effect (probably s/b an = sign)
|
||||
#pragma warning(3:4288) // nonstandard extension used (loop counter)
|
||||
#pragma warning(3:4532) // jump out of __finally block
|
||||
#pragma warning(error:4312) // cast of 32-bit int to 64-bit ptr
|
||||
#pragma warning(error:4296) // expression is always true/false
|
||||
#pragma warning(3:4546) // function call before comma missing argument list
|
||||
// disable until __noop(arg,arg,arg) doesn't generate false hits.
|
||||
// #pragma warning(3:4547) // '<' : operator before comma has no effect; expected operator with side-effect
|
||||
// #pragma warning(3:4548) // expression before comma has no effect; expected expression with side-effect
|
||||
|
||||
#pragma warning(disable:4197) // illegal use of const/volatile: qualifier ignored (disabled until sources fixed)
|
||||
#pragma warning(disable:4675) // picked overload found via Koenig lookup
|
||||
#pragma warning(disable:4356) // static member cannot be initialized via derived class
|
||||
|
||||
#ifndef __cplusplus
|
||||
#undef try
|
||||
#undef except
|
||||
#undef finally
|
||||
#undef leave
|
||||
#define try __try
|
||||
#define except __except
|
||||
#define finally __finally
|
||||
#define leave __leave
|
||||
#endif
|
||||
|
||||
#if _MSC_VER <= 1400
|
||||
#pragma warning(disable: 4068) // turn off unknown pragma warning so prefast pragmas won't show
|
||||
// show up in build.wrn/build.err
|
||||
#endif
|
||||
|
||||
#if defined(_M_IX86) && _MSC_FULL_VER >= 13102154
|
||||
#define __TYPENAME typename
|
||||
#else
|
||||
#define __TYPENAME
|
||||
#endif
|
||||
|
||||
66
base/ntos/BUILD/makefile
Normal file
66
base/ntos/BUILD/makefile
Normal file
@ -0,0 +1,66 @@
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
#
|
||||
# You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
# If you do not agree to the terms, do not use the code.
|
||||
#
|
||||
|
||||
kernel = wrk$(machine)
|
||||
|
||||
asobjs=
|
||||
ccobjs=
|
||||
ccarchobjs=
|
||||
|
||||
default: kernelexp kernellib kernelexe
|
||||
|
||||
nodefault=1
|
||||
!include $(ntos)\BUILD\makefile.build
|
||||
|
||||
linklibpath = -LIBPATH:$(topobj) -LIBPATH:PREBUILT\$(targ)
|
||||
ntoswrklib = ntoswrk.lib
|
||||
ntosarchlib = ntosarch.lib
|
||||
bootlibs = bootvid.lib sdbapint.lib kdcom.lib
|
||||
|
||||
fullkernel = EXE\$(kernel)
|
||||
|
||||
# kernel link definitions
|
||||
LINKFLAGS = -IGNORE:4087,4001,4010,4037,4039,4065,4070,4078,4087,4089,4221,4198 -WX -NODEFAULTLIB -machine:$(machine) $(linklibpath)
|
||||
LINK = link.exe -nologo
|
||||
LINKEDIT = link.exe -edit -nologo
|
||||
|
||||
LIB = $(LIB) $(linklibpath)
|
||||
|
||||
!if "$(targ)" == "i386"
|
||||
archlinkopts = -safeseh -functionpadmin:5 -debugtype:cv,fixup -STACK:0x40000,0x2000 -align:0x1000
|
||||
hotpatch = -stub:PREBUILT\i386\stub512.com
|
||||
entrypoint = KiSystemStartup@4
|
||||
!else
|
||||
archlinkopts = -functionpadmin:6 -debugtype:cv,fixup,pdata -STACK:0x80000,0x2000
|
||||
hotpatch = PREBUILT\amd64\hotpatch.obj
|
||||
LINKFLAGS = -IGNORE:4108,4088,4218,4218,4235 $(LINKFLAGS)
|
||||
LIBFLAGS = -IGNORE:4108,4088,4218,4218,4235 $(LIBFLAGS)
|
||||
entrypoint = KiSystemStartup
|
||||
!endif
|
||||
|
||||
ntosmerge = -merge:PAGECONST=PAGE -merge:INITCONST=INIT -merge:INITDATA=INIT -merge:PAGELKCONST=PAGELK \
|
||||
-merge:PAGEVRFY_CONST=PAGEVRFY -MERGE:_PAGE=PAGE -MERGE:_TEXT=.text -merge:.rdata=.text
|
||||
|
||||
ntosversion = -release -version:5.2 -osversion:5.2 -subsystem:native,5.02
|
||||
|
||||
ntoslinkopts = $(ntosversion) $(ntosmerge) -SECTION:INIT,d -OPT:REF -OPT:ICF -INCREMENTAL:NO \
|
||||
-FULLBUILD -debug $(archlinkopts) -opt:nowin98 -pdbcompress -driver
|
||||
|
||||
kernelexp:
|
||||
copy ..\init\ntoskrnl.src+..\init\$(targ)def.src $(OBJ)\$(kernel).pp
|
||||
$(CC) $(CFLAGS0) -EP $(OBJ)\$(kernel).pp > $(fullkernel).def
|
||||
-del $(OBJ)\$(kernel).pp
|
||||
$(LIB) $(LIBFLAGS) -IGNORE:4001 $(OBJ)\*.lib $(ntoswrklib) -def:$(fullkernel).def -out:$(fullkernel).lib
|
||||
|
||||
kernellib:
|
||||
$(LIB) $(fullkernel).lib $(ntosarchlib) -out:$(fullkernel).lib
|
||||
|
||||
kernelexe:
|
||||
$(LINK) $(LINKFLAGS) $(ntoslinkopts) -out:$(fullkernel).exe -map:$(fullkernel).map -pdb:$(fullkernel).pdb -entry:$(entrypoint) \
|
||||
$(hotpatch) PREBUILT\$(targ)\ntoskrnl.res $(OBJ)\ntkrnlmp.obj $(OBJ)\*.lib $(ntoswrklib) hal.lib $(fullkernel).exp $(bootlibs)
|
||||
$(LINKEDIT) -section:.rsrc,!d $(fullkernel).exe
|
||||
|
||||
83
base/ntos/BUILD/makefile.build
Normal file
83
base/ntos/BUILD/makefile.build
Normal file
@ -0,0 +1,83 @@
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
#
|
||||
# You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
# If you do not agree to the terms, do not use the code.
|
||||
#
|
||||
|
||||
!if !defined(ntos) || !defined(pub) || !defined(module) || !defined(topobj) || !defined(targ) || ("$(targ)" != "i386" && "$(targ)" != "amd64")
|
||||
!ERROR Usage: nmake ntos=ntosdir pub=pubdir module=ntossubdir targ=[i386|amd64]
|
||||
!endif
|
||||
|
||||
!if "$(targ)" == "i386"
|
||||
targdefs = -D_X86_=1 -Di386=1 -DSTD_CALL -DFPO=0
|
||||
targaopts = -safeseh -coff -Zm
|
||||
targcopts = -Gm- -Gz -GX- -G6 -Ze -Gi- -QIfdiv- -Z7 -Oxs -Oy-
|
||||
targlopts =
|
||||
machine = x86
|
||||
archml = ml
|
||||
!else
|
||||
targdefs = -D_WIN64 -D_AMD64_ -DAMD64
|
||||
targaopts =
|
||||
targcopts = -Wp64 -Oxt -EHs-c- /Oxt -Gs12288 -GL- -MT -U_MT
|
||||
targlopts = -IGNORE:4108,4088,4218,4218,4235
|
||||
machine = amd64
|
||||
archml = ml64
|
||||
!endif
|
||||
|
||||
tempdir = $(topobj)\temp
|
||||
ipub = $(pub)\internal
|
||||
baseinc = $(ntos)\..\inc
|
||||
|
||||
incs = -I..\$(targ) -I. -I$(ntos)\$(module) -I$(ntos)\inc -I$(pub)\ddk\inc -I$(ipub)\ds\inc -I$(ipub)\sdktools\inc \
|
||||
-I$(baseinc) -I$(ipub)\base\inc -I$(pub)\sdk\inc -I$(pub)\sdk\inc\crt -I$(pub)\halkit\inc
|
||||
|
||||
defs = $(targdefs) -DCONDITION_HANDLING=1 -DNT_INST=0 -DWIN32=100 -D_NT1X_=100 -DWINNT=1 \
|
||||
-D_WIN32_WINNT=0x0502 -DWINVER=0x0502 -D_WIN32_IE=0x0603 -DWIN32_LEAN_AND_MEAN=1 -DDBG=0 -DDEVL=1 \
|
||||
-D__BUILDMACHINE__=WRK1.2(university) -DNDEBUG -D_NTSYSTEM_ -DNT_SMT -DNTOS_KERNEL_RUNTIME=1
|
||||
|
||||
aopts = -Cx -Zi $(targaopts)
|
||||
copts = -Zl -Zp8 -Gy -cbstring -W3 -WX -GR- -GF -GS $(targcopts)
|
||||
compilerwarnings = -FI$(ntos)\BUILD\WARNING.h
|
||||
|
||||
AS = $(archml).exe -nologo
|
||||
AFLAGS = $(aopts) $(incs) -Foobj$(targ)\ $(defs) $(specialaflags)
|
||||
|
||||
CC = cl.exe -nologo
|
||||
CFLAGS0 = $(copts) $(incs) -Foobj$(targ)\ $(defs) $(specialcflags)
|
||||
CFLAGS = $(CFLAGS0) $(compilerwarnings)
|
||||
|
||||
LIBFLAGS = $(targlopts) -IGNORE:4010,4037,4039,4065,4070,4078,4087,4089,4221,4198 -WX -nodefaultlib -machine:$(machine)
|
||||
LIB = lib.exe -nologo
|
||||
|
||||
OBJ = obj$(targ)
|
||||
|
||||
!ifndef nodefault
|
||||
default: build $(localtargets)
|
||||
!endif
|
||||
|
||||
# assembly files
|
||||
{..\$(targ)\}.asm{$(OBJ)\}.obj::
|
||||
$(AS) $(AFLAGS) -c $<
|
||||
|
||||
# arch-specific C files
|
||||
{..\$(targ)\}.c{$(OBJ)\}.obj::
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
# C files
|
||||
{..\}.c{$(OBJ)\}.obj::
|
||||
$(CC) $(CFLAGS) -c $<
|
||||
|
||||
# library
|
||||
$(topobj)\$(library).lib: $(asobjs) $(ccarchobjs) $(ccobjs)
|
||||
@echo linking $(library).lib
|
||||
$(LIB) $(LIBFLAGS) -out:$@ $**
|
||||
|
||||
# pseudo targets
|
||||
build: $(topobj)\$(library).lib
|
||||
|
||||
clean: clean0 $(localclean)
|
||||
|
||||
clean0:
|
||||
-del $(asobjs) $(ccarchobjs) $(ccobjs) $(extraobjs)
|
||||
|
||||
1
base/ntos/BUILD/objamd64/Placeholder.txt
Normal file
1
base/ntos/BUILD/objamd64/Placeholder.txt
Normal file
@ -0,0 +1 @@
|
||||
*** This file is here solely to preserve the directory structure when WRK is xcopy'ed ***
|
||||
1
base/ntos/BUILD/obji386/Placeholder.txt
Normal file
1
base/ntos/BUILD/obji386/Placeholder.txt
Normal file
@ -0,0 +1 @@
|
||||
*** This file is here solely to preserve the directory structure when WRK is xcopy'ed ***
|
||||
340
base/ntos/VDM/i386/vdm.inc
Normal file
340
base/ntos/VDM/i386/vdm.inc
Normal file
@ -0,0 +1,340 @@
|
||||
;++
|
||||
;
|
||||
; Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
;
|
||||
; You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
; If you do not agree to the terms, do not use the code.
|
||||
;
|
||||
;
|
||||
; Module Name:
|
||||
;
|
||||
; vdm.inc
|
||||
;
|
||||
; Abstract:
|
||||
;
|
||||
; This module contains the structure and constant definitions for
|
||||
; the vdm component
|
||||
;--
|
||||
.386p
|
||||
|
||||
TRUE equ 1
|
||||
FALSE equ 0
|
||||
|
||||
;
|
||||
; Macro's to only do locked memory operations on MP systems
|
||||
;
|
||||
|
||||
IFDEF NT_UP
|
||||
MPLOCK equ <>
|
||||
ELSE
|
||||
MPLOCK equ <lock>
|
||||
ENDIF
|
||||
|
||||
page , 132
|
||||
subttl "Macro to dispatch exception"
|
||||
|
||||
;++
|
||||
;
|
||||
; Macro Description:
|
||||
;
|
||||
; This macro allocates exception record on stack, sets up exception
|
||||
; record using specified parameters and finally sets up arguments
|
||||
; and calls _KiDispatchException.
|
||||
;
|
||||
; Arguments:
|
||||
;
|
||||
; ExcepCode - Exception code to put into exception record
|
||||
; ExceptFlags - Exception flags to put into exception record
|
||||
; ExceptRecord - Associated exception record
|
||||
; ExceptAddress - Addr of instruction which the hardware exception occurs
|
||||
; NumParms - Number of additional parameters
|
||||
; ParameterList - the additional parameter list
|
||||
;
|
||||
; Return Value:
|
||||
;
|
||||
; None.
|
||||
;
|
||||
;--
|
||||
|
||||
DISPATCH_EXCEPTION macro ExceptCode, ExceptFlags, ExceptRecord, ExceptAddress,\
|
||||
NumParms, ParameterList
|
||||
local de10, de20
|
||||
|
||||
; Set up exception record for raising exception
|
||||
|
||||
?i = 0
|
||||
sub esp, ExceptionRecordSize + NumParms * 4
|
||||
; allocate exception record
|
||||
mov dword ptr [esp]+ErExceptionCode, ExceptCode
|
||||
; set up exception code
|
||||
mov dword ptr [esp]+ErExceptionFlags, ExceptFlags
|
||||
; set exception flags
|
||||
mov dword ptr [esp]+ErExceptionRecord, ExceptRecord
|
||||
; set associated exception record
|
||||
mov dword ptr [esp]+ErExceptionAddress, ExceptAddress
|
||||
mov dword ptr [esp]+ErNumberParameters, NumParms
|
||||
; set number of parameters
|
||||
IRP z, <ParameterList>
|
||||
mov dword ptr [esp]+(ErExceptionInformation+?i*4), z
|
||||
?i = ?i + 1
|
||||
ENDM
|
||||
|
||||
; set up arguments and call _KiDispatchException
|
||||
|
||||
mov ecx, esp ; (ecx)->exception record
|
||||
|
||||
test dword ptr [ebp]+TsEFlags,EFLAGS_V86_MASK
|
||||
jz de10
|
||||
|
||||
mov eax,0FFFFh
|
||||
jmp de20
|
||||
|
||||
de10: mov eax,[ebp]+TsSegCs
|
||||
de20: and eax,MODE_MASK
|
||||
|
||||
; 1 - set first chance TRUE
|
||||
; eax - PreviousMode
|
||||
; ebp - trap frame addr
|
||||
; 0 - Null exception frame
|
||||
; ecx - exception record addr
|
||||
|
||||
; dispatchexception as appropriate
|
||||
stdCall _KiDispatchException, <ecx, 0, ebp, eax, 1>
|
||||
add esp,ExceptionRecordSize + NumParms*4
|
||||
|
||||
ENDM
|
||||
|
||||
|
||||
;
|
||||
; Prefix Flags
|
||||
;
|
||||
|
||||
PREFIX_ES equ 00000100h
|
||||
PREFIX_CS equ 00000200h
|
||||
PREFIX_SS equ 00000400h
|
||||
PREFIX_DS equ 00000800h
|
||||
PREFIX_FS equ 00001000h
|
||||
PREFIX_GS equ 00002000h
|
||||
PREFIX_OPER32 equ 00004000h
|
||||
PREFIX_ADDR32 equ 00008000h
|
||||
PREFIX_LOCK equ 00010000h
|
||||
PREFIX_REPNE equ 00020000h
|
||||
PREFIX_REP equ 00040000h
|
||||
PREFIX_SEG_ALL equ 00003f00h
|
||||
|
||||
NUM_OPCODE equ 255
|
||||
;
|
||||
; Reginfo structure
|
||||
;
|
||||
|
||||
RegInfo struc
|
||||
RiSegSs dd 0
|
||||
RiEsp dd 0
|
||||
RiEFlags dd 0
|
||||
RiSegCs dd 0
|
||||
RiEip dd 0
|
||||
RiTrapFrame dd 0
|
||||
RiCsLimit dd 0
|
||||
RiCsBase dd 0
|
||||
RiCsFlags dd 0
|
||||
RiSsLimit dd 0
|
||||
RiSsBase dd 0
|
||||
RiSsFlags dd 0
|
||||
RiPrefixFlags dd 0
|
||||
RiOperand dd 0
|
||||
RegInfo ends
|
||||
REGINFOSIZE EQU 56
|
||||
|
||||
MAX_VDM_ADDR EQU 0FFFFFFH
|
||||
|
||||
DR7_GLOBAL EQU 002AAH
|
||||
|
||||
;
|
||||
;Fast Read/Write Defines
|
||||
;
|
||||
|
||||
SVC_DEMFASTREAD equ 42h
|
||||
SVC_DEMFASTWRITE equ 43h
|
||||
DOS_BOP equ 50h
|
||||
|
||||
;
|
||||
;
|
||||
; Size of Exception Record
|
||||
;
|
||||
|
||||
ExceptionRecordSize = (ErNumberParameters + 4 + 3) AND 0fffffffcH ;
|
||||
|
||||
;
|
||||
; Magic value
|
||||
;
|
||||
|
||||
OPCODE_MAGIC equ 00f5ah
|
||||
|
||||
;++
|
||||
; diBEGIN - BEGIN index table
|
||||
;
|
||||
; ENTRY name = name of di table
|
||||
; badindex = local label for unspecified entries
|
||||
;
|
||||
; EXIT ?sindex = specific entry index
|
||||
; ?badindex = default index for unspecified entries
|
||||
;--
|
||||
|
||||
diBEGIN macro name,badindex ;; Beginning of dispatch table
|
||||
?sopc = 0
|
||||
?badindex = badindex
|
||||
name label byte ;; Start of dispatch table
|
||||
endm
|
||||
|
||||
;++
|
||||
; dtI - SPECIFIC index table entry
|
||||
;
|
||||
; ENTRY opc = opcode value
|
||||
; index = INDEX_ value corresponding to opcode
|
||||
; ?badindex = unspecified entry index
|
||||
; ?sopc = specific entry index
|
||||
;
|
||||
; EXIT Unspecified entries prior to "index" filled in;
|
||||
; Specified entry filled in.
|
||||
; ?sopc = next index to fill in;
|
||||
;--
|
||||
|
||||
dtI macro opc,index ;; Specific entry in dispatch table
|
||||
if ?sopc gt opc
|
||||
%out dtI: opcode out of order
|
||||
.err
|
||||
else
|
||||
if ?sopc lt opc ;; Fill unspecified entries
|
||||
rept opc - ?sopc
|
||||
db ?badindex
|
||||
endm
|
||||
endif
|
||||
db index ;; Specified entry
|
||||
?sopc = opc+1 ;; Set new start index
|
||||
endif
|
||||
endm
|
||||
|
||||
;++
|
||||
; diEND - END index table
|
||||
;
|
||||
; ENTRY index = highest entry in table
|
||||
; ?sopc = specific entry index
|
||||
;
|
||||
; EXIT rest of the table filled in
|
||||
;--
|
||||
|
||||
diEND macro index ;; End of dispatch table
|
||||
if ?sopc lt index ;; Fill in rest of table
|
||||
rept index - ?sopc
|
||||
db ?badindex
|
||||
endm
|
||||
db ?badindex ;; fill in last entry of table!
|
||||
endif
|
||||
endm
|
||||
|
||||
|
||||
;++
|
||||
; dtBEGIN - BEGIN dispatch table
|
||||
;
|
||||
; ENTRY name = name of dt table
|
||||
; badaddr = local label for unspecified entries
|
||||
;
|
||||
; EXIT ?sindex = specific entry index
|
||||
; ?badaddr = default handler for unspecified entries
|
||||
;--
|
||||
|
||||
dtBEGIN macro name,badaddr ;; Beginning of dispatch table
|
||||
?sindex = 0
|
||||
?badaddr = badaddr
|
||||
name label dword ;; Start of dispatch table
|
||||
endm
|
||||
|
||||
;++
|
||||
; dtS - SPECIFIC dispatch table entry
|
||||
;
|
||||
; ENTRY index = index of entry
|
||||
; addr = address of handler
|
||||
; ?badaddr = unspecified entry handler
|
||||
; ?sindex = specific entry index
|
||||
;
|
||||
; EXIT Unspecified entries prior to "index" filled in;
|
||||
; Specified entry filled in.
|
||||
; ?sindex = next index to fill in;
|
||||
;--
|
||||
|
||||
dtS macro index,addr ;; Specific entry in dispatch table
|
||||
if ?sindex gt index
|
||||
%out dtS: index out of order
|
||||
.err
|
||||
else
|
||||
if ?sindex lt index ;; Fill unspecified entries
|
||||
rept index - ?sindex
|
||||
dd offset FLAT:?badaddr
|
||||
endm
|
||||
endif
|
||||
dd offset FLAT:addr ;; Specified entry
|
||||
?sindex = index+1 ;; Set new start index
|
||||
endif
|
||||
endm
|
||||
|
||||
;++
|
||||
; dtEND - END dispatch table
|
||||
;
|
||||
; ENTRY index = highest entry in table
|
||||
; ?sindex = specific entry index
|
||||
;
|
||||
; EXIT rest of the table filled in
|
||||
;--
|
||||
|
||||
dtEND macro index ;; End of dispatch table
|
||||
if ?sindex lt index ;; Fill in rest of table
|
||||
rept index - ?sindex
|
||||
dd offset FLAT:?badaddr
|
||||
endm
|
||||
dd offset FLAT:?badaddr ;; fill in last entry of table!
|
||||
endif
|
||||
endm
|
||||
|
||||
;++
|
||||
; CsToLinearPM
|
||||
;
|
||||
;--
|
||||
|
||||
CsToLinearPM macro sel, erraddr
|
||||
lea eax,[esi].RiCsLimit
|
||||
push eax
|
||||
lea eax,[esi].RiCsBase
|
||||
push eax
|
||||
lea eax,[esi].RiCsFlags
|
||||
push eax
|
||||
push sel
|
||||
|
||||
call _Ki386GetSelectorParameters@16
|
||||
or al,al
|
||||
jz erraddr
|
||||
|
||||
test [esi].RiCsFlags,SEL_TYPE_EXECUTE
|
||||
jz erraddr
|
||||
|
||||
test [esi].RiCsFlags,SEL_TYPE_2GIG
|
||||
jz @f
|
||||
|
||||
; Correct limit value for granularity
|
||||
shl [esi].RiCsLimit,12
|
||||
or [esi].RiCsLimit,0FFFh
|
||||
@@:
|
||||
endm
|
||||
|
||||
;++
|
||||
; CsToLinearV86
|
||||
;
|
||||
;--
|
||||
|
||||
CsToLinearV86 macro
|
||||
movzx eax,word ptr [esi].RiSegCs
|
||||
shl eax,4
|
||||
mov [esi].RiCsBase,eax
|
||||
mov [esi].RiCsLimit,0FFFFh
|
||||
mov [esi].RiCsFlags,0
|
||||
endm
|
||||
|
||||
28
base/ntos/VERIFIER/halverifier.h
Normal file
28
base/ntos/VERIFIER/halverifier.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
halverifier.c
|
||||
|
||||
Abstract:
|
||||
|
||||
This module contains the routines to verify hal usage & apis.
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef _HAL_VERIFIER_
|
||||
#define _HAL_VERIFIER_
|
||||
|
||||
VOID
|
||||
VfHalVerifierInitialize(
|
||||
VOID
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
66
base/ntos/VERIFIER/vfbugcheck.h
Normal file
66
base/ntos/VERIFIER/vfbugcheck.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
vfbugcheck.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This header defines the prototypes and constants required for verifier
|
||||
bugchecks.
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef _VFBUGCHECK_H_
|
||||
#define _VFBUGCHECK_H_
|
||||
|
||||
extern LONG IovpInitCalled;
|
||||
|
||||
#define KDASSERT(x) { if (KdDebuggerEnabled) { ASSERT(x) ; } }
|
||||
|
||||
#define ASSERT_SPINLOCK_HELD(x)
|
||||
|
||||
#define DCPARAM_ROUTINE 0x00000001
|
||||
#define DCPARAM_IRP 0x00000008
|
||||
#define DCPARAM_IRPSNAP 0x00000040
|
||||
#define DCPARAM_DEVOBJ 0x00000200
|
||||
#define DCPARAM_STATUS 0x00001000
|
||||
#define DCPARAM_ULONG 0x00008000
|
||||
#define DCPARAM_PVOID 0x00040000
|
||||
|
||||
#define WDM_FAIL_ROUTINE(ParenWrappedParamList) \
|
||||
{ \
|
||||
if (IovpInitCalled) { \
|
||||
VfBugcheckThrowIoException##ParenWrappedParamList;\
|
||||
} \
|
||||
}
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfBugcheckInit(
|
||||
VOID
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
VfBugcheckThrowIoException(
|
||||
IN DCERROR_ID MessageIndex,
|
||||
IN ULONG MessageParameterMask,
|
||||
...
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
VfBugcheckThrowException(
|
||||
IN PVFMESSAGE_TEMPLATE_TABLE MessageTable OPTIONAL,
|
||||
IN VFMESSAGE_ERRORID MessageID,
|
||||
IN PCSTR MessageParamFormat,
|
||||
IN va_list * MessageParameters
|
||||
);
|
||||
|
||||
#endif // _VFBUGCHECK_H_
|
||||
|
||||
28
base/ntos/VERIFIER/vfddi.h
Normal file
28
base/ntos/VERIFIER/vfddi.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
vfddi.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This header contains prototypes for verifier device driver interfaces.
|
||||
|
||||
--*/
|
||||
|
||||
VOID
|
||||
VfDdiInit(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
VfDdiExposeWmiObjects(
|
||||
VOID
|
||||
);
|
||||
|
||||
440
base/ntos/VERIFIER/vfdeadlock.h
Normal file
440
base/ntos/VERIFIER/vfdeadlock.h
Normal file
@ -0,0 +1,440 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
vfdeadlock.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Detect deadlocks in arbitrary synchronization objects.
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef _VF_DEADLOCK_
|
||||
#define _VF_DEADLOCK_
|
||||
|
||||
//
|
||||
// Deadlock detection package initialization.
|
||||
//
|
||||
|
||||
VOID
|
||||
VfDeadlockDetectionInitialize(
|
||||
);
|
||||
|
||||
//
|
||||
// Functions called from IovCallDriver (driver verifier replacement for
|
||||
// IoCallDriver) just before and after the real call to the driver is made.
|
||||
//
|
||||
|
||||
BOOLEAN
|
||||
VfDeadlockBeforeCallDriver (
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN OUT PIRP Irp
|
||||
);
|
||||
|
||||
VOID
|
||||
VfDeadlockAfterCallDriver (
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN OUT PIRP Irp,
|
||||
IN BOOLEAN PagingIrp
|
||||
);
|
||||
|
||||
//
|
||||
// Maximum depth of stack traces captured.
|
||||
//
|
||||
|
||||
#define VI_MAX_STACK_DEPTH 8
|
||||
|
||||
#define NO_OF_DEADLOCK_PARTICIPANTS 32
|
||||
|
||||
//
|
||||
// VI_DEADLOCK_NODE
|
||||
//
|
||||
|
||||
typedef struct _VI_DEADLOCK_NODE {
|
||||
|
||||
//
|
||||
// Node representing the acquisition of the previous resource.
|
||||
//
|
||||
|
||||
struct _VI_DEADLOCK_NODE * Parent;
|
||||
|
||||
//
|
||||
// Node representing the next resource acquisitions, that are
|
||||
// done after acquisition of the current resource.
|
||||
//
|
||||
|
||||
struct _LIST_ENTRY ChildrenList;
|
||||
|
||||
//
|
||||
// Field used to chain siblings in the tree. A parent node has the
|
||||
// ChildrenList field as the head of the children list that is chained
|
||||
// with the Siblings field.
|
||||
//
|
||||
|
||||
struct _LIST_ENTRY SiblingsList;
|
||||
|
||||
union {
|
||||
|
||||
//
|
||||
// List of nodes representing the same resource acquisition
|
||||
// as the current node but in different contexts (lock combinations).
|
||||
//
|
||||
|
||||
struct _LIST_ENTRY ResourceList;
|
||||
|
||||
//
|
||||
// Used to chain free nodes. This is used only after the node has
|
||||
// been deleted (resource was freed). Nodes are kept in a cache
|
||||
// to reduce contention for the kernel pool.
|
||||
//
|
||||
|
||||
struct _LIST_ENTRY FreeListEntry;
|
||||
};
|
||||
|
||||
//
|
||||
// Back pointer to the descriptor for this resource.
|
||||
//
|
||||
|
||||
struct _VI_DEADLOCK_RESOURCE * Root;
|
||||
|
||||
//
|
||||
// When we find a deadlock, we keep this info around in order to
|
||||
// be able to identify the parties involved who have caused
|
||||
// the deadlock.
|
||||
//
|
||||
|
||||
struct _VI_DEADLOCK_THREAD * ThreadEntry;
|
||||
|
||||
//
|
||||
// Fields used for decision making within the deadlock analysis
|
||||
// algorithm.
|
||||
//
|
||||
// Active: 1 if the node represents a resource currently acquired,
|
||||
// 0 if resource was acquired in the past.
|
||||
//
|
||||
// OnlyTryAcquiredUsed: 1 if resource was always acquired with TryAcquire.
|
||||
// 0 if at least once normal acquire was used. A node that uses
|
||||
// only TryAcquire cannot be involved in a deadlock.
|
||||
//
|
||||
// ReleasedOutOfOrder: 1 if the resource was at least once released
|
||||
// out of order. The flag is used while looking for cycles because
|
||||
// this type of nodes will appear as part of the cycle but there is
|
||||
// no deadlock.
|
||||
//
|
||||
// SequenceNumber: field that gets a unique stamp during each deadlock
|
||||
// analysis run. It helps figure out if the node was touched
|
||||
// already in the current graph traversal.
|
||||
//
|
||||
|
||||
struct {
|
||||
|
||||
ULONG Active : 1;
|
||||
ULONG OnlyTryAcquireUsed : 1;
|
||||
ULONG ReleasedOutOfOrder : 1;
|
||||
ULONG SequenceNumber : 29;
|
||||
};
|
||||
|
||||
//
|
||||
// Stack traces for the resource acquisition moment.
|
||||
// Used when displaying deadlock proofs. On free builds
|
||||
// anything other than the first entry (return address)
|
||||
// may be bogus in case stack trace capturing failed.
|
||||
//
|
||||
|
||||
PVOID StackTrace[VI_MAX_STACK_DEPTH];
|
||||
PVOID ParentStackTrace[VI_MAX_STACK_DEPTH];
|
||||
|
||||
} VI_DEADLOCK_NODE, *PVI_DEADLOCK_NODE;
|
||||
|
||||
//
|
||||
// VI_DEADLOCK_RESOURCE
|
||||
//
|
||||
|
||||
typedef struct _VI_DEADLOCK_RESOURCE {
|
||||
|
||||
//
|
||||
// Resource type (mutex, spinlock, etc.).
|
||||
//
|
||||
|
||||
VI_DEADLOCK_RESOURCE_TYPE Type;
|
||||
|
||||
//
|
||||
// Resource flags
|
||||
//
|
||||
// NodeCount : number of resource nodes created for this resource.
|
||||
//
|
||||
// RecursionCount : number of times this resource has been recursively acquired
|
||||
// It makes sense to put this counter in the resource because as long as
|
||||
// resource is acquired only one thread can operate on it.
|
||||
//
|
||||
|
||||
struct {
|
||||
ULONG NodeCount : 16;
|
||||
ULONG RecursionCount : 16;
|
||||
};
|
||||
|
||||
//
|
||||
// The address of the synchronization object used by the kernel.
|
||||
//
|
||||
|
||||
PVOID ResourceAddress;
|
||||
|
||||
//
|
||||
// The thread that currently owns the resource. The field is
|
||||
// null if nobody owns the resource.
|
||||
//
|
||||
|
||||
struct _VI_DEADLOCK_THREAD * ThreadOwner;
|
||||
|
||||
//
|
||||
// List of resource nodes representing acquisitions of this resource.
|
||||
//
|
||||
|
||||
LIST_ENTRY ResourceList;
|
||||
|
||||
union {
|
||||
|
||||
//
|
||||
// List used for chaining resources from a hash bucket.
|
||||
//
|
||||
|
||||
LIST_ENTRY HashChainList;
|
||||
|
||||
//
|
||||
// Used to chain free resources. This list is used only after
|
||||
// the resource has been freed and we put the structure
|
||||
// into a cache to reduce kernel pool contention.
|
||||
//
|
||||
|
||||
LIST_ENTRY FreeListEntry;
|
||||
};
|
||||
|
||||
//
|
||||
// Stack trace of the resource creator. On free builds we
|
||||
// may have here only a return address that is bubbled up
|
||||
// from verifier thunks.
|
||||
//
|
||||
|
||||
PVOID StackTrace [VI_MAX_STACK_DEPTH];
|
||||
|
||||
//
|
||||
// Stack trace for last acquire
|
||||
//
|
||||
|
||||
PVOID LastAcquireTrace [VI_MAX_STACK_DEPTH];
|
||||
|
||||
//
|
||||
// Stack trace for last release
|
||||
//
|
||||
|
||||
PVOID LastReleaseTrace [VI_MAX_STACK_DEPTH];
|
||||
|
||||
} VI_DEADLOCK_RESOURCE, * PVI_DEADLOCK_RESOURCE;
|
||||
|
||||
//
|
||||
// VI_DEADLOCK_THREAD
|
||||
//
|
||||
|
||||
typedef struct _VI_DEADLOCK_THREAD {
|
||||
|
||||
//
|
||||
// Kernel thread address
|
||||
//
|
||||
|
||||
PKTHREAD Thread;
|
||||
|
||||
//
|
||||
// The node representing the last resource acquisition made by
|
||||
// this thread.
|
||||
//
|
||||
|
||||
//
|
||||
// We have separate graph branches for spinlocks and other types
|
||||
// of locks (fast mutex, mutex). The thread keeps a list of both types
|
||||
// so that we can properly release locks
|
||||
//
|
||||
|
||||
PVI_DEADLOCK_NODE CurrentSpinNode;
|
||||
PVI_DEADLOCK_NODE CurrentOtherNode;
|
||||
|
||||
union {
|
||||
|
||||
//
|
||||
// Thread list. It is used for chaining into a hash bucket.
|
||||
//
|
||||
|
||||
LIST_ENTRY ListEntry;
|
||||
|
||||
//
|
||||
// Used to chain free nodes. The list is used only after we decide
|
||||
// to delete the thread structure (possibly because it does not
|
||||
// hold resources anymore). Keeping the structures in a cache
|
||||
// reduces pool contention.
|
||||
//
|
||||
|
||||
LIST_ENTRY FreeListEntry;
|
||||
};
|
||||
|
||||
//
|
||||
// Count of resources currently acquired by a thread. When this becomes
|
||||
// zero the thread will be destroyed. The count goes up during acquire
|
||||
// and down during release.
|
||||
//
|
||||
|
||||
ULONG NodeCount;
|
||||
|
||||
//
|
||||
// This counter is used to count how many IoCallDriver() calls with
|
||||
// paging IRPs are active for this thread. This information is necessary
|
||||
// to decide if we should temporarily disable deadlock verification
|
||||
// to avoid known lack of lock hierarchy issues in file system drivers.
|
||||
//
|
||||
|
||||
ULONG PagingCount;
|
||||
|
||||
} VI_DEADLOCK_THREAD, *PVI_DEADLOCK_THREAD;
|
||||
|
||||
//
|
||||
// Deadlock verifier globals
|
||||
//
|
||||
|
||||
typedef struct _VI_DEADLOCK_GLOBALS {
|
||||
|
||||
//
|
||||
// Structure counters: [0] - current, [1] - maximum
|
||||
//
|
||||
|
||||
ULONG Nodes[2];
|
||||
ULONG Resources[2];
|
||||
ULONG Threads[2];
|
||||
|
||||
//
|
||||
// Maximum times for Acquire() and Release() in ticks.
|
||||
//
|
||||
|
||||
LONGLONG TimeAcquire;
|
||||
LONGLONG TimeRelease;
|
||||
|
||||
//
|
||||
// Total number of kernel pool bytes used by the deadlock verifier
|
||||
//
|
||||
|
||||
SIZE_T BytesAllocated;
|
||||
|
||||
//
|
||||
// Resource and thread collection.
|
||||
//
|
||||
|
||||
PLIST_ENTRY ResourceDatabase;
|
||||
PLIST_ENTRY ThreadDatabase;
|
||||
|
||||
//
|
||||
// How many times ExAllocatePool failed on us?
|
||||
// If this is >0 we stop deadlock verification.
|
||||
//
|
||||
|
||||
ULONG AllocationFailures;
|
||||
|
||||
//
|
||||
// How many nodes have been trimmed when we decided to forget
|
||||
// partially the history of some resources.
|
||||
//
|
||||
|
||||
ULONG NodesTrimmedBasedOnAge;
|
||||
ULONG NodesTrimmedBasedOnCount;
|
||||
|
||||
//
|
||||
// Deadlock analysis statistics
|
||||
//
|
||||
|
||||
ULONG NodesSearched;
|
||||
ULONG MaxNodesSearched;
|
||||
ULONG SequenceNumber;
|
||||
|
||||
ULONG RecursionDepthLimit;
|
||||
ULONG SearchedNodesLimit;
|
||||
|
||||
ULONG DepthLimitHits;
|
||||
ULONG SearchLimitHits;
|
||||
|
||||
//
|
||||
// Number of times we have to exhonerate a deadlock because
|
||||
// it was protected by a common resource (e.g. thread 1 takes ABC,
|
||||
// thread 2 takes ACB -- this will get flagged initially by our algorithm
|
||||
// since B&C are taken out of order but is not actually a deadlock.
|
||||
//
|
||||
|
||||
ULONG ABC_ACB_Skipped;
|
||||
|
||||
ULONG OutOfOrderReleases;
|
||||
ULONG NodesReleasedOutOfOrder;
|
||||
|
||||
#if DBG
|
||||
//
|
||||
// How many locks are held simultaneously while the system is running?
|
||||
//
|
||||
|
||||
ULONG NodeLevelCounter[8];
|
||||
ULONG GraphNodes[8];
|
||||
#endif
|
||||
|
||||
ULONG TotalReleases;
|
||||
ULONG RootNodesDeleted;
|
||||
|
||||
//
|
||||
// Used to control how often we delete portions of the dependency
|
||||
// graph.
|
||||
//
|
||||
|
||||
ULONG ForgetHistoryCounter;
|
||||
|
||||
//
|
||||
// How often was a worker items dispatched to trim the
|
||||
// pool cache.
|
||||
//
|
||||
|
||||
ULONG PoolTrimCounter;
|
||||
|
||||
//
|
||||
// Caches of freed structures (thread, resource, node) used to
|
||||
// decrease kernel pool contention.
|
||||
//
|
||||
|
||||
LIST_ENTRY FreeResourceList;
|
||||
LIST_ENTRY FreeThreadList;
|
||||
LIST_ENTRY FreeNodeList;
|
||||
|
||||
ULONG FreeResourceCount;
|
||||
ULONG FreeThreadCount;
|
||||
ULONG FreeNodeCount;
|
||||
|
||||
//
|
||||
// Resource address that caused the deadlock
|
||||
//
|
||||
|
||||
PVOID Instigator;
|
||||
|
||||
//
|
||||
// Number of participants in the deadlock
|
||||
//
|
||||
|
||||
ULONG NumberOfParticipants;
|
||||
|
||||
//
|
||||
// List of the nodes that participate in the deadlock
|
||||
//
|
||||
|
||||
PVI_DEADLOCK_NODE Participant [NO_OF_DEADLOCK_PARTICIPANTS];
|
||||
|
||||
LOGICAL CacheReductionInProgress;
|
||||
} VI_DEADLOCK_GLOBALS, *PVI_DEADLOCK_GLOBALS;
|
||||
|
||||
#endif
|
||||
|
||||
31
base/ntos/VERIFIER/vfdebug.h
Normal file
31
base/ntos/VERIFIER/vfdebug.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
vfdebug.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This header contains debugging macros used by the driver verifier code.
|
||||
|
||||
--*/
|
||||
|
||||
extern ULONG VfSpewLevel;
|
||||
|
||||
#if DBG
|
||||
#define VERIFIER_DBGPRINT(txt,level) \
|
||||
{ \
|
||||
if (VfSpewLevel>(level)) { \
|
||||
DbgPrint##txt; \
|
||||
}\
|
||||
}
|
||||
#else
|
||||
#define VERIFIER_DBGPRINT(txt,level)
|
||||
#endif
|
||||
|
||||
60
base/ntos/VERIFIER/vfdef.h
Normal file
60
base/ntos/VERIFIER/vfdef.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
vfdef.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This header collects together the various files necessary to create a basic
|
||||
set of definitions for the verifier.
|
||||
|
||||
--*/
|
||||
|
||||
//
|
||||
// Disable W4 level warnings generated by public headers.
|
||||
//
|
||||
|
||||
#include "vfpragma.h"
|
||||
|
||||
#include "ntos.h"
|
||||
#include "vfdebug.h"
|
||||
#include "vfmacro.h"
|
||||
#include "vfinit.h"
|
||||
#include "vfsettings.h"
|
||||
#include "vfmessage.h"
|
||||
#include "vfbugcheck.h"
|
||||
#include "vfprint.h"
|
||||
#include "vfutil.h"
|
||||
#include "vfstack.h"
|
||||
#include "vftriage.h"
|
||||
#include "vfirp.h"
|
||||
#include "vfirpdb.h"
|
||||
#include "vfirplog.h"
|
||||
#include "vfdevobj.h"
|
||||
#include "vfpacket.h"
|
||||
#include "halverifier.h"
|
||||
#include "vfdeadlock.h"
|
||||
|
||||
#include "..\io\trackirp.h"
|
||||
#include "..\io\sessnirp.h"
|
||||
|
||||
#include "..\ob\obvutil.h"
|
||||
#include "..\io\iovutil.h"
|
||||
#include "..\io\pnpmgr\ppvutil.h"
|
||||
|
||||
#include "vffilter.h"
|
||||
#include "vfmajor.h"
|
||||
#include "vfpnp.h"
|
||||
#include "vfpower.h"
|
||||
#include "vfwmi.h"
|
||||
#include "vfgeneric.h"
|
||||
#include "vfrandom.h"
|
||||
#include "vfddi.h"
|
||||
|
||||
69
base/ntos/VERIFIER/vfdevobj.h
Normal file
69
base/ntos/VERIFIER/vfdevobj.h
Normal file
@ -0,0 +1,69 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
vfdevobj.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This header exposes function hooks that verify drivers properly manage
|
||||
device objects.
|
||||
|
||||
--*/
|
||||
|
||||
typedef enum {
|
||||
|
||||
VF_DEVOBJ_PDO = 0,
|
||||
VF_DEVOBJ_BUS_FILTER,
|
||||
VF_DEVOBJ_LOWER_DEVICE_FILTER,
|
||||
VF_DEVOBJ_LOWER_CLASS_FILTER,
|
||||
VF_DEVOBJ_FDO,
|
||||
VF_DEVOBJ_UPPER_DEVICE_FILTER,
|
||||
VF_DEVOBJ_UPPER_CLASS_FILTER
|
||||
|
||||
} VF_DEVOBJ_TYPE, *PVF_DEVOBJ_TYPE;
|
||||
|
||||
VOID
|
||||
VfDevObjPreAddDevice(
|
||||
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
||||
IN PDRIVER_OBJECT DriverObject,
|
||||
IN PDRIVER_ADD_DEVICE AddDeviceFunction,
|
||||
IN VF_DEVOBJ_TYPE DevObjType
|
||||
);
|
||||
|
||||
VOID
|
||||
VfDevObjPostAddDevice(
|
||||
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
||||
IN PDRIVER_OBJECT DriverObject,
|
||||
IN PDRIVER_ADD_DEVICE AddDeviceFunction,
|
||||
IN VF_DEVOBJ_TYPE DevObjType,
|
||||
IN NTSTATUS Result
|
||||
);
|
||||
|
||||
VOID
|
||||
VfDevObjAdjustFdoForVerifierFilters(
|
||||
IN OUT PDEVICE_OBJECT *FunctionalDeviceObject
|
||||
);
|
||||
|
||||
VOID
|
||||
VerifierIoAttachDeviceToDeviceStack(
|
||||
IN PDEVICE_OBJECT NewDevice,
|
||||
IN PDEVICE_OBJECT ExistingDevice
|
||||
);
|
||||
|
||||
VOID
|
||||
VerifierIoDetachDevice(
|
||||
IN PDEVICE_OBJECT LowerDevice
|
||||
);
|
||||
|
||||
VOID
|
||||
VerifierIoDeleteDevice(
|
||||
IN PDEVICE_OBJECT DeviceObject
|
||||
);
|
||||
|
||||
34
base/ntos/VERIFIER/vffilter.h
Normal file
34
base/ntos/VERIFIER/vffilter.h
Normal file
@ -0,0 +1,34 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
vffilter.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This header contains prototypes for using the verifier driver filter.
|
||||
|
||||
--*/
|
||||
|
||||
VOID
|
||||
VfFilterInit(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
VfFilterAttach(
|
||||
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
||||
IN VF_DEVOBJ_TYPE DeviceObjectType
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
VfFilterIsVerifierFilterObject(
|
||||
IN PDEVICE_OBJECT DeviceObject
|
||||
);
|
||||
|
||||
24
base/ntos/VERIFIER/vfgeneric.h
Normal file
24
base/ntos/VERIFIER/vfgeneric.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
vfgeneric.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This header contains prototypes for verifying generic IRPs are handled
|
||||
correctly.
|
||||
|
||||
--*/
|
||||
|
||||
VOID
|
||||
VfGenericInit(
|
||||
VOID
|
||||
);
|
||||
|
||||
24
base/ntos/VERIFIER/vfinit.h
Normal file
24
base/ntos/VERIFIER/vfinit.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
vfinit.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This header exposes the routines necessary to initialize the driver verifier.
|
||||
|
||||
--*/
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfInitVerifier(
|
||||
IN ULONG MmFlags
|
||||
);
|
||||
|
||||
216
base/ntos/VERIFIER/vfirp.h
Normal file
216
base/ntos/VERIFIER/vfirp.h
Normal file
@ -0,0 +1,216 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
vfirp.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This module contains prototypes for functions used to manage IRPs used in
|
||||
the verification process.
|
||||
|
||||
--*/
|
||||
|
||||
struct _IOV_STACK_LOCATION;
|
||||
struct _IOV_REQUEST_PACKET;
|
||||
struct _IOFCALLDRIVER_STACKDATA;
|
||||
|
||||
typedef struct _IOV_STACK_LOCATION *PIOV_STACK_LOCATION;
|
||||
typedef struct _IOV_REQUEST_PACKET *PIOV_REQUEST_PACKET;
|
||||
typedef struct _IOV_SESSION_DATA *PIOV_SESSION_DATA;
|
||||
typedef struct _IOFCALLDRIVER_STACKDATA *PIOFCALLDRIVER_STACKDATA;
|
||||
|
||||
//
|
||||
// Mini-snapshots of the IRP are stored on the stack for cases when the
|
||||
// verifier needs to inform the developer as to the mistake, but no longer
|
||||
// has the original IRP in memory. Because these may be stored on the stack,
|
||||
// they need to be small and light.
|
||||
//
|
||||
typedef struct _IRP_MINI_SNAPSHOT {
|
||||
|
||||
PIRP Irp;
|
||||
IO_STACK_LOCATION IoStackLocation;
|
||||
|
||||
} IRP_MINI_SNAPSHOT, *PIRP_MINI_SNAPSHOT;
|
||||
|
||||
typedef struct _IOV_STACK_LOCATION {
|
||||
|
||||
BOOLEAN InUse;
|
||||
ULONG Flags;
|
||||
PIOV_STACK_LOCATION RequestsFirstStackLocation;
|
||||
LIST_ENTRY CallStackData;
|
||||
PIO_STACK_LOCATION IrpSp;
|
||||
PVOID LastDispatch;
|
||||
LARGE_INTEGER PerfDispatchStart;
|
||||
LARGE_INTEGER PerfStackLocationStart;
|
||||
PDEVICE_OBJECT ReferencingObject;
|
||||
LONG ReferencingCount;
|
||||
IO_STATUS_BLOCK InitialStatusBlock;
|
||||
IO_STATUS_BLOCK LastStatusBlock;
|
||||
PETHREAD ThreadDispatchedTo;
|
||||
|
||||
} IOV_STACK_LOCATION;
|
||||
|
||||
typedef struct _IOV_SESSION_DATA {
|
||||
|
||||
PIOV_REQUEST_PACKET IovRequestPacket;
|
||||
LONG SessionRefCount;
|
||||
LIST_ENTRY SessionLink;
|
||||
ULONG SessionFlags;
|
||||
|
||||
PETHREAD OriginatorThread;
|
||||
PDEVICE_OBJECT DeviceLastCalled; // Last device called
|
||||
ULONG ForwardMethod;
|
||||
PIRP BestVisibleIrp;
|
||||
PVERIFIER_SETTINGS_SNAPSHOT VerifierSettings;
|
||||
IOV_STACK_LOCATION StackData[ANYSIZE_ARRAY];
|
||||
|
||||
} IOV_SESSION_DATA;
|
||||
|
||||
typedef struct _IOFCALLDRIVER_STACKDATA {
|
||||
|
||||
PIOV_SESSION_DATA IovSessionData;
|
||||
PIOV_STACK_LOCATION IovStackLocation;
|
||||
PIOV_REQUEST_PACKET IovPacket;
|
||||
ULONG Flags;
|
||||
LIST_ENTRY SharedLocationList;
|
||||
PDRIVER_DISPATCH DispatchRoutine;
|
||||
NTSTATUS ExpectedStatus;
|
||||
NTSTATUS NewStatus;
|
||||
PDEVICE_OBJECT RemovePdo;
|
||||
IRP_MINI_SNAPSHOT IrpSnapshot;
|
||||
|
||||
} IOFCALLDRIVER_STACKDATA;
|
||||
|
||||
typedef struct _IOFCOMPLETEREQUEST_STACKDATA {
|
||||
|
||||
PIOV_SESSION_DATA IovSessionData;
|
||||
PIOV_REQUEST_PACKET IovRequestPacket;
|
||||
BOOLEAN IsRemoveIrp;
|
||||
LONG LocationsAdvanced;
|
||||
ULONG RaisedCount;
|
||||
KIRQL PreviousIrql;
|
||||
PVOID CompletionRoutine;
|
||||
|
||||
} IOFCOMPLETEREQUEST_STACKDATA, *PIOFCOMPLETEREQUEST_STACKDATA;
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfIrpInit(
|
||||
VOID
|
||||
);
|
||||
|
||||
PIRP
|
||||
FASTCALL
|
||||
VfIrpAllocate(
|
||||
IN CCHAR StackSize
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfIrpMakeTouchable(
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfIrpMakeUntouchable(
|
||||
IN PIRP Irp OPTIONAL
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfIrpFree(
|
||||
IN PIRP Irp OPTIONAL
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VerifierIoAllocateIrp1(
|
||||
IN CCHAR StackSize,
|
||||
IN BOOLEAN ChargeQuota,
|
||||
IN OUT PIRP *IrpPointer
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VerifierIoAllocateIrp2(
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VerifierIoFreeIrp(
|
||||
IN PIRP Irp,
|
||||
IN OUT PBOOLEAN FreeHandled
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VerifierIoInitializeIrp(
|
||||
IN OUT PIRP Irp,
|
||||
IN USHORT PacketSize,
|
||||
IN CCHAR StackSize,
|
||||
IN OUT PBOOLEAN InitializeHandled
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
FASTCALL
|
||||
VfIrpReserveCallStackData(
|
||||
IN PIRP Irp,
|
||||
OUT PIOFCALLDRIVER_STACKDATA *IofCallDriverStackData
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfIrpPrepareAllocaCallStackData(
|
||||
OUT PIOFCALLDRIVER_STACKDATA IofCallDriverStackData
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfIrpReleaseCallStackData(
|
||||
IN PIOFCALLDRIVER_STACKDATA IofCallDriverStackData OPTIONAL
|
||||
);
|
||||
|
||||
//
|
||||
// VfIrpCallDriverPreprocess is a macro function that may do an alloca as
|
||||
// part of it's operation. As such callers must be careful not to use
|
||||
// variable length arrays in a scope that encompasses
|
||||
// VfIrpCallDriverPreProcess but not VfIrpCallDriverPostProcess.
|
||||
//
|
||||
#define VfIrpCallDriverPreProcess(DeviceObject, IrpPointer, CallStackData, CallerAddress) \
|
||||
if (!VfIrpReserveCallStackData(*(IrpPointer), (CallStackData))) { \
|
||||
*(CallStackData) = alloca(sizeof(IOFCALLDRIVER_STACKDATA)); \
|
||||
VfIrpPrepareAllocaCallStackData(*(CallStackData)); \
|
||||
} \
|
||||
IovpCallDriver1((DeviceObject), (IrpPointer), *(CallStackData), (CallerAddress))
|
||||
|
||||
#define VfIrpCallDriverPostProcess(DeviceObject, FinalStatus, CallStackData) \
|
||||
IovpCallDriver2(DeviceObject, FinalStatus, CallStackData); \
|
||||
VfIrpReleaseCallStackData(CallStackData)
|
||||
|
||||
BOOLEAN
|
||||
VfIrpSendSynchronousIrp(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIO_STACK_LOCATION TopStackLocation,
|
||||
IN BOOLEAN Untouchable,
|
||||
IN NTSTATUS InitialStatus,
|
||||
IN ULONG_PTR InitialInformation OPTIONAL,
|
||||
OUT ULONG_PTR *FinalInformation OPTIONAL,
|
||||
OUT NTSTATUS *FinalStatus OPTIONAL
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfIrpWatermark(
|
||||
IN PIRP Irp,
|
||||
IN ULONG Flags
|
||||
);
|
||||
|
||||
128
base/ntos/VERIFIER/vfirpdb.h
Normal file
128
base/ntos/VERIFIER/vfirpdb.h
Normal file
@ -0,0 +1,128 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
vfirpdb.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This header exposes prototypes for functions used to manage the database of
|
||||
IRP tracking data.
|
||||
|
||||
--*/
|
||||
|
||||
struct _IOV_DATABASE_HEADER;
|
||||
typedef struct _IOV_DATABASE_HEADER IOV_DATABASE_HEADER;
|
||||
typedef struct _IOV_DATABASE_HEADER *PIOV_DATABASE_HEADER;
|
||||
|
||||
typedef enum _IOV_REFERENCE_TYPE {
|
||||
|
||||
IOVREFTYPE_PACKET = 0,
|
||||
IOVREFTYPE_POINTER
|
||||
|
||||
} IOV_REFERENCE_TYPE;
|
||||
|
||||
typedef enum {
|
||||
|
||||
IRPDBEVENT_POINTER_COUNT_ZERO = 1,
|
||||
IRPDBEVENT_REFERENCE_COUNT_ZERO
|
||||
|
||||
} IRP_DATABASE_EVENT;
|
||||
|
||||
typedef VOID (*PFN_IRPDBEVENT_CALLBACK)(
|
||||
IN PIOV_DATABASE_HEADER IovHeader,
|
||||
IN PIRP TrackedIrp OPTIONAL,
|
||||
IN IRP_DATABASE_EVENT Event
|
||||
);
|
||||
|
||||
typedef struct _IOV_DATABASE_HEADER {
|
||||
|
||||
PIRP TrackedIrp; // Tracked IRP
|
||||
KSPIN_LOCK HeaderLock; // Spinlock on data structure
|
||||
KIRQL LockIrql; // IRQL taken at.
|
||||
LONG ReferenceCount; // # of reasons to keep this packet
|
||||
LONG PointerCount; // # of reasons to track by irp addr
|
||||
ULONG HeaderFlags;
|
||||
LIST_ENTRY HashLink; // Link in hash table.
|
||||
LIST_ENTRY ChainLink; // Head is HeadPacket
|
||||
PIOV_DATABASE_HEADER ChainHead; // First packet in a chain.
|
||||
PFN_IRPDBEVENT_CALLBACK NotificationCallback;
|
||||
};
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfIrpDatabaseInit(
|
||||
VOID
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
FASTCALL
|
||||
VfIrpDatabaseEntryInsertAndLock(
|
||||
IN PIRP Irp,
|
||||
IN PFN_IRPDBEVENT_CALLBACK NotificationCallback,
|
||||
IN OUT PIOV_DATABASE_HEADER IovHeader
|
||||
);
|
||||
|
||||
PIOV_DATABASE_HEADER
|
||||
FASTCALL
|
||||
VfIrpDatabaseEntryFindAndLock(
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfIrpDatabaseEntryAcquireLock(
|
||||
IN PIOV_DATABASE_HEADER IovHeader OPTIONAL
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfIrpDatabaseEntryReleaseLock(
|
||||
IN PIOV_DATABASE_HEADER IovHeader
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfIrpDatabaseEntryReference(
|
||||
IN PIOV_DATABASE_HEADER IovHeader,
|
||||
IN IOV_REFERENCE_TYPE IovRefType
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfIrpDatabaseEntryDereference(
|
||||
IN PIOV_DATABASE_HEADER IovHeader,
|
||||
IN IOV_REFERENCE_TYPE IovRefType
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfIrpDatabaseEntryAppendToChain(
|
||||
IN OUT PIOV_DATABASE_HEADER IovExistingHeader,
|
||||
IN OUT PIOV_DATABASE_HEADER IovNewHeader
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfIrpDatabaseEntryRemoveFromChain(
|
||||
IN OUT PIOV_DATABASE_HEADER IovHeader
|
||||
);
|
||||
|
||||
PIOV_DATABASE_HEADER
|
||||
FASTCALL
|
||||
VfIrpDatabaseEntryGetChainPrevious(
|
||||
IN PIOV_DATABASE_HEADER IovHeader
|
||||
);
|
||||
|
||||
PIOV_DATABASE_HEADER
|
||||
FASTCALL
|
||||
VfIrpDatabaseEntryGetChainNext(
|
||||
IN PIOV_DATABASE_HEADER IovHeader
|
||||
);
|
||||
|
||||
75
base/ntos/VERIFIER/vfirplog.h
Normal file
75
base/ntos/VERIFIER/vfirplog.h
Normal file
@ -0,0 +1,75 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
vfirplog.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This header exposes functions for logging IRP events.
|
||||
|
||||
--*/
|
||||
|
||||
//
|
||||
// Log-snapshots are retrievable by user mode for profiling and targetted
|
||||
// probing of stacks. Content-wise they are heavier.
|
||||
//
|
||||
typedef struct _IRPLOG_SNAPSHOT {
|
||||
|
||||
ULONG Count;
|
||||
UCHAR MajorFunction;
|
||||
UCHAR MinorFunction;
|
||||
UCHAR Flags;
|
||||
UCHAR Control;
|
||||
ULONGLONG ArgArray[4];
|
||||
|
||||
} IRPLOG_SNAPSHOT, *PIRPLOG_SNAPSHOT;
|
||||
|
||||
VOID
|
||||
VfIrpLogInit(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
VfIrpLogRecordEvent(
|
||||
IN PVERIFIER_SETTINGS_SNAPSHOT VerifierSettingsSnapshot,
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
ULONG
|
||||
VfIrpLogGetIrpDatabaseSiloCount(
|
||||
VOID
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
VfIrpLogLockDatabase(
|
||||
IN ULONG SiloNumber
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
VfIrpLogRetrieveWmiData(
|
||||
IN ULONG SiloNumber,
|
||||
OUT PUCHAR OutputBuffer OPTIONAL,
|
||||
OUT ULONG *OffsetInstanceNameOffsets,
|
||||
OUT ULONG *InstanceCount,
|
||||
OUT ULONG *DataBlockOffset,
|
||||
OUT ULONG *TotalRequiredSize
|
||||
);
|
||||
|
||||
VOID
|
||||
VfIrpLogUnlockDatabase(
|
||||
IN ULONG SiloNumber
|
||||
);
|
||||
|
||||
VOID
|
||||
VfIrpLogDeleteDeviceLogs(
|
||||
IN PDEVICE_OBJECT DeviceObject
|
||||
);
|
||||
|
||||
35
base/ntos/VERIFIER/vfmacro.h
Normal file
35
base/ntos/VERIFIER/vfmacro.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
vfmacro.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This header contains a collection of macros used by the verifier.
|
||||
|
||||
--*/
|
||||
|
||||
|
||||
//
|
||||
// This macro takes an array and returns the number of elements in it.
|
||||
//
|
||||
#define ARRAY_COUNT(array) (sizeof(array)/sizeof(array[0]))
|
||||
|
||||
//
|
||||
// This macro takes a value and an alignment and rounds the entry up
|
||||
// appropriately. The alignment MUST be a power of two!
|
||||
//
|
||||
#define ALIGN_UP_ULONG(value, alignment) (((value)+(alignment)-1)&(~(alignment-1)))
|
||||
|
||||
//
|
||||
// This macro compares two guids in their binary form for equivalence.
|
||||
//
|
||||
#define IS_EQUAL_GUID(a,b) (RtlCompareMemory(a, b, sizeof(GUID)) == sizeof(GUID))
|
||||
|
||||
221
base/ntos/VERIFIER/vfmajor.h
Normal file
221
base/ntos/VERIFIER/vfmajor.h
Normal file
@ -0,0 +1,221 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
vfmajor.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This header contains prototypes for per-major IRP code verification.
|
||||
|
||||
--*/
|
||||
|
||||
//
|
||||
// Use this major code to register a handler for default or all IRPs (context
|
||||
// specific to function)
|
||||
//
|
||||
#define IRP_MJ_ALL_MAJORS 0xFF
|
||||
|
||||
typedef VOID (FASTCALL *PFN_DUMP_IRP_STACK)(
|
||||
IN PIO_STACK_LOCATION IrpSp
|
||||
);
|
||||
|
||||
typedef VOID (FASTCALL *PFN_VERIFY_NEW_REQUEST)(
|
||||
IN PIOV_REQUEST_PACKET IrpTrackingData,
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIO_STACK_LOCATION IrpLastSp OPTIONAL,
|
||||
IN PIO_STACK_LOCATION IrpSp,
|
||||
IN PIOV_STACK_LOCATION StackLocationData,
|
||||
IN PVOID CallerAddress OPTIONAL
|
||||
);
|
||||
|
||||
typedef VOID (FASTCALL *PFN_VERIFY_IRP_STACK_DOWNWARD)(
|
||||
IN PIOV_REQUEST_PACKET IovPacket,
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIO_STACK_LOCATION IrpLastSp OPTIONAL,
|
||||
IN PIO_STACK_LOCATION IrpSp,
|
||||
IN PIOV_STACK_LOCATION RequestHeadLocationData,
|
||||
IN PIOV_STACK_LOCATION StackLocationData,
|
||||
IN PVOID CallerAddress OPTIONAL
|
||||
);
|
||||
|
||||
typedef VOID (FASTCALL *PFN_VERIFY_IRP_STACK_UPWARD)(
|
||||
IN PIOV_REQUEST_PACKET IovPacket,
|
||||
IN PIO_STACK_LOCATION IrpSp,
|
||||
IN PIOV_STACK_LOCATION RequestHeadLocationData,
|
||||
IN PIOV_STACK_LOCATION StackLocationData,
|
||||
IN BOOLEAN IsNewlyCompleted,
|
||||
IN BOOLEAN RequestFinalized
|
||||
);
|
||||
|
||||
typedef BOOLEAN (FASTCALL *PFN_IS_SYSTEM_RESTRICTED_IRP)(
|
||||
IN PIO_STACK_LOCATION IrpSp
|
||||
);
|
||||
|
||||
typedef BOOLEAN (FASTCALL *PFN_ADVANCE_IRP_STATUS)(
|
||||
IN PIO_STACK_LOCATION IrpSp,
|
||||
IN NTSTATUS OriginalStatus,
|
||||
IN OUT NTSTATUS *StatusToAdvance
|
||||
);
|
||||
|
||||
typedef BOOLEAN (FASTCALL *PFN_IS_VALID_IRP_STATUS)(
|
||||
IN PIO_STACK_LOCATION IrpSp,
|
||||
IN NTSTATUS Status
|
||||
);
|
||||
|
||||
typedef BOOLEAN (FASTCALL *PFN_IS_NEW_REQUEST)(
|
||||
IN PIO_STACK_LOCATION IrpLastSp OPTIONAL,
|
||||
IN PIO_STACK_LOCATION IrpSp
|
||||
);
|
||||
|
||||
typedef VOID (FASTCALL *PFN_VERIFY_NEW_IRP)(
|
||||
IN PIOV_REQUEST_PACKET IovPacket,
|
||||
IN PIRP Irp,
|
||||
IN PIO_STACK_LOCATION IrpSp,
|
||||
IN PIOV_STACK_LOCATION StackLocationData,
|
||||
IN PVOID CallerAddress OPTIONAL
|
||||
);
|
||||
|
||||
typedef VOID (FASTCALL *PFN_VERIFY_FINAL_IRP_STACK)(
|
||||
IN PIOV_REQUEST_PACKET IovPacket,
|
||||
IN PIO_STACK_LOCATION IrpSp
|
||||
);
|
||||
|
||||
typedef VOID (FASTCALL *PFN_TEST_STARTED_PDO_STACK)(
|
||||
IN PDEVICE_OBJECT PhysicalDeviceObject
|
||||
);
|
||||
|
||||
typedef LOGICAL (FASTCALL *PFN_BUILD_LOG_ENTRY)(
|
||||
IN PIRP Irp,
|
||||
IN ULONG CurrentCount,
|
||||
IN PIRPLOG_SNAPSHOT CurrentEntryArray,
|
||||
OUT PIRPLOG_SNAPSHOT IrpSnapshot
|
||||
);
|
||||
|
||||
VOID
|
||||
VfMajorInit(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfMajorRegisterHandlers(
|
||||
IN UCHAR IrpMajorCode,
|
||||
IN PFN_DUMP_IRP_STACK DumpIrpStack OPTIONAL,
|
||||
IN PFN_VERIFY_NEW_REQUEST VerifyNewRequest OPTIONAL,
|
||||
IN PFN_VERIFY_IRP_STACK_DOWNWARD VerifyStackDownward OPTIONAL,
|
||||
IN PFN_VERIFY_IRP_STACK_UPWARD VerifyStackUpward OPTIONAL,
|
||||
IN PFN_IS_SYSTEM_RESTRICTED_IRP IsSystemRestrictedIrp OPTIONAL,
|
||||
IN PFN_ADVANCE_IRP_STATUS AdvanceIrpStatus OPTIONAL,
|
||||
IN PFN_IS_VALID_IRP_STATUS IsValidIrpStatus OPTIONAL,
|
||||
IN PFN_IS_NEW_REQUEST IsNewRequest OPTIONAL,
|
||||
IN PFN_VERIFY_NEW_IRP VerifyNewIrp OPTIONAL,
|
||||
IN PFN_VERIFY_FINAL_IRP_STACK VerifyFinalIrpStack OPTIONAL,
|
||||
IN PFN_TEST_STARTED_PDO_STACK TestStartedPdoStack OPTIONAL,
|
||||
IN PFN_BUILD_LOG_ENTRY BuildIrpLogEntry OPTIONAL
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfMajorDumpIrpStack(
|
||||
IN PIO_STACK_LOCATION IrpSp
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfMajorVerifyNewRequest(
|
||||
IN PIOV_REQUEST_PACKET IovPacket,
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIO_STACK_LOCATION IrpLastSp OPTIONAL,
|
||||
IN PIO_STACK_LOCATION IrpSp,
|
||||
IN PIOV_STACK_LOCATION StackLocationData,
|
||||
IN PVOID CallerAddress OPTIONAL
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfMajorVerifyIrpStackDownward(
|
||||
IN PIOV_REQUEST_PACKET IovPacket,
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIO_STACK_LOCATION IrpLastSp OPTIONAL,
|
||||
IN PIO_STACK_LOCATION IrpSp,
|
||||
IN PIOV_STACK_LOCATION StackLocationData,
|
||||
IN PVOID CallerAddress OPTIONAL
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfMajorVerifyIrpStackUpward(
|
||||
IN PIOV_REQUEST_PACKET IovPacket,
|
||||
IN PIO_STACK_LOCATION IrpSp,
|
||||
IN PIOV_STACK_LOCATION StackLocationData,
|
||||
IN BOOLEAN IsNewlyCompleted,
|
||||
IN BOOLEAN RequestFinalized
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
FASTCALL
|
||||
VfMajorIsSystemRestrictedIrp(
|
||||
IN PIO_STACK_LOCATION IrpSp
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
FASTCALL
|
||||
VfMajorAdvanceIrpStatus(
|
||||
IN PIO_STACK_LOCATION IrpSp,
|
||||
IN NTSTATUS OriginalStatus,
|
||||
IN OUT NTSTATUS *StatusToAdvance
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
FASTCALL
|
||||
VfMajorIsValidIrpStatus(
|
||||
IN PIO_STACK_LOCATION IrpSp,
|
||||
IN NTSTATUS Status
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
FASTCALL
|
||||
VfMajorIsNewRequest(
|
||||
IN PIO_STACK_LOCATION IrpLastSp OPTIONAL,
|
||||
IN PIO_STACK_LOCATION IrpSp
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfMajorVerifyNewIrp(
|
||||
IN PIOV_REQUEST_PACKET IovPacket,
|
||||
IN PIRP Irp,
|
||||
IN PIO_STACK_LOCATION IrpSp,
|
||||
IN PIOV_STACK_LOCATION StackLocationData,
|
||||
IN PVOID CallerAddress OPTIONAL
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfMajorVerifyFinalIrpStack(
|
||||
IN PIOV_REQUEST_PACKET IovPacket,
|
||||
IN PIO_STACK_LOCATION IrpSp
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfMajorTestStartedPdoStack(
|
||||
IN PDEVICE_OBJECT PhysicalDeviceObject
|
||||
);
|
||||
|
||||
LOGICAL
|
||||
FASTCALL
|
||||
VfMajorBuildIrpLogEntry(
|
||||
IN PIRP Irp,
|
||||
IN ULONG CurrentCount,
|
||||
IN PIRPLOG_SNAPSHOT CurrentEntryArray,
|
||||
OUT PIRPLOG_SNAPSHOT IrpSnapshot
|
||||
);
|
||||
|
||||
237
base/ntos/VERIFIER/vfmessage.h
Normal file
237
base/ntos/VERIFIER/vfmessage.h
Normal file
@ -0,0 +1,237 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
vfmessage.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This module contains prototypes for functions used to retrieve text and
|
||||
flags associated with each error.
|
||||
|
||||
--*/
|
||||
|
||||
//
|
||||
// The verifier uses tables of messages and with indexes into the tables.
|
||||
//
|
||||
typedef ULONG VFMESSAGE_TABLEID;
|
||||
typedef ULONG VFMESSAGE_ERRORID;
|
||||
|
||||
//
|
||||
// VFM_ flags control how a verifier message is handled.
|
||||
//
|
||||
// VFM_FLAG_INITIALIZED - Set when the error template has been updated with
|
||||
// error-class information
|
||||
//
|
||||
// VFM_FLAG_BEEP - Set if error should beep in debugger
|
||||
//
|
||||
// VFM_FLAG_ZAPPED - Set if error was "zapped" (ie prints instead of
|
||||
// stops) via debugger
|
||||
//
|
||||
// VFM_FLAG_CLEARED - Set if error was cleared (disabled) in debugger
|
||||
//
|
||||
// VFM_DEPLOYMENT_FAILURE - Set if the error is severe enough to warrant
|
||||
// removal of the driver from a production system
|
||||
//
|
||||
// VFM_LOGO_FAILURE - Set if the error should disallow certification
|
||||
// for the hardware or the driver
|
||||
//
|
||||
// VFM_IGNORE_DRIVER_LIST - Set if error should fire regardless of whether
|
||||
// the offending driver is being verified or not.
|
||||
//
|
||||
|
||||
#define VFM_FLAG_INITIALIZED 0x00000001
|
||||
#define VFM_FLAG_BEEP 0x00000002
|
||||
#define VFM_FLAG_ZAPPED 0x00000004
|
||||
#define VFM_FLAG_CLEARED 0x00000008
|
||||
#define VFM_DEPLOYMENT_FAILURE 0x00000010
|
||||
#define VFM_LOGO_FAILURE 0x00000020
|
||||
#define VFM_IGNORE_DRIVER_LIST 0x00000040
|
||||
|
||||
//
|
||||
// A message class contains VFM_ flags and some generic text describing the
|
||||
// problem class.
|
||||
//
|
||||
typedef struct _VFMESSAGE_CLASS {
|
||||
|
||||
ULONG ClassFlags;
|
||||
PCSTR MessageClassText;
|
||||
|
||||
} VFMESSAGE_CLASS, *PVFMESSAGE_CLASS;
|
||||
|
||||
typedef VFMESSAGE_CLASS const *PCVFMESSAGE_CLASS;
|
||||
|
||||
//
|
||||
// Individual error template. Identifies the index, the message class it's
|
||||
// associated with, the parameters it takes along with the formatted text it
|
||||
// displays. Note the ulong flags field - this should always be preinited to
|
||||
// zero!
|
||||
//
|
||||
typedef struct _VFMESSAGE_TEMPLATE {
|
||||
|
||||
VFMESSAGE_ERRORID MessageID;
|
||||
PCVFMESSAGE_CLASS MessageClass;
|
||||
ULONG Flags;
|
||||
PCSTR ParamString;
|
||||
PCSTR MessageText;
|
||||
|
||||
} VFMESSAGE_TEMPLATE, *PVFMESSAGE_TEMPLATE;
|
||||
|
||||
//
|
||||
// Message index 0 is reserved for use in the override tables
|
||||
//
|
||||
#define VIMESSAGE_ALL_IDS 0
|
||||
|
||||
//
|
||||
// An override entry allows the verifier to special case generic assertions
|
||||
// that occur against specific drivers. This is done by overriding the error
|
||||
// class on the fly.
|
||||
//
|
||||
typedef struct _VFMESSAGE_OVERRIDE {
|
||||
|
||||
VFMESSAGE_ERRORID MessageID;
|
||||
PCSTR DriverName;
|
||||
PCVFMESSAGE_CLASS ReplacementClass;
|
||||
|
||||
} VFMESSAGE_OVERRIDE, *PVFMESSAGE_OVERRIDE;
|
||||
|
||||
typedef VFMESSAGE_OVERRIDE const *PCVFMESSAGE_OVERRIDE;
|
||||
|
||||
//
|
||||
// The table of errors. Contains the TableID (used for internal lookup),
|
||||
// bugcheck major ID, array of messages and array of overrides
|
||||
//
|
||||
typedef struct _VFMESSAGE_TEMPLATE_TABLE {
|
||||
|
||||
VFMESSAGE_TABLEID TableID;
|
||||
ULONG BugCheckMajor;
|
||||
PVFMESSAGE_TEMPLATE TemplateArray;
|
||||
ULONG TemplateCount;
|
||||
PCVFMESSAGE_OVERRIDE OverrideArray;
|
||||
ULONG OverrideCount;
|
||||
|
||||
} VFMESSAGE_TEMPLATE_TABLE, *PVFMESSAGE_TEMPLATE_TABLE;
|
||||
|
||||
//
|
||||
// Retrieves an internal error table based on ID.
|
||||
//
|
||||
VOID
|
||||
VfMessageRetrieveInternalTable(
|
||||
IN VFMESSAGE_TABLEID TableID,
|
||||
OUT PVFMESSAGE_TEMPLATE_TABLE *MessageTable
|
||||
);
|
||||
|
||||
//
|
||||
// Retrieves and formats the appropriate error message.
|
||||
//
|
||||
VOID
|
||||
VfMessageRetrieveErrorData(
|
||||
IN PVFMESSAGE_TEMPLATE_TABLE MessageTable OPTIONAL,
|
||||
IN VFMESSAGE_ERRORID MessageID,
|
||||
IN PSTR AnsiDriverName,
|
||||
OUT ULONG *BugCheckMajor,
|
||||
OUT PCVFMESSAGE_CLASS *MessageClass,
|
||||
OUT PCSTR *MessageTextTemplate,
|
||||
OUT PULONG *TemplateFlags
|
||||
);
|
||||
|
||||
//
|
||||
// This file contains a set of internal message tables.
|
||||
//
|
||||
// The IO Verifier Table Index is...
|
||||
//
|
||||
#define VFMESSAGE_TABLE_IOVERIFIER 1
|
||||
|
||||
//
|
||||
// IO Verifier Messages
|
||||
//
|
||||
typedef enum _DCERROR_ID {
|
||||
|
||||
DCERROR_UNSPECIFIED = 0x200,
|
||||
DCERROR_DELETE_WHILE_ATTACHED,
|
||||
DCERROR_DETACH_NOT_ATTACHED,
|
||||
DCERROR_CANCELROUTINE_FORWARDED,
|
||||
DCERROR_NULL_DEVOBJ_FORWARDED,
|
||||
DCERROR_QUEUED_IRP_FORWARDED,
|
||||
DCERROR_NEXTIRPSP_DIRTY,
|
||||
DCERROR_IRPSP_COPIED,
|
||||
DCERROR_INSUFFICIENT_STACK_LOCATIONS,
|
||||
DCERROR_QUEUED_IRP_COMPLETED,
|
||||
DCERROR_FREE_OF_INUSE_TRACKED_IRP,
|
||||
DCERROR_FREE_OF_INUSE_IRP,
|
||||
DCERROR_FREE_OF_THREADED_IRP,
|
||||
DCERROR_REINIT_OF_ALLOCATED_IRP_WITH_QUOTA,
|
||||
DCERROR_PNP_IRP_BAD_INITIAL_STATUS,
|
||||
DCERROR_POWER_IRP_BAD_INITIAL_STATUS,
|
||||
DCERROR_WMI_IRP_BAD_INITIAL_STATUS,
|
||||
DCERROR_SKIPPED_DEVICE_OBJECT,
|
||||
DCERROR_BOGUS_FUNC_TRASHED,
|
||||
DCERROR_BOGUS_STATUS_TRASHED,
|
||||
DCERROR_BOGUS_INFO_TRASHED,
|
||||
DCERROR_PNP_FAILURE_FORWARDED,
|
||||
DCERROR_PNP_IRP_STATUS_RESET,
|
||||
DCERROR_PNP_IRP_NEEDS_HANDLING,
|
||||
DCERROR_PNP_IRP_HANDS_OFF,
|
||||
DCERROR_POWER_FAILURE_FORWARDED,
|
||||
DCERROR_POWER_IRP_STATUS_RESET,
|
||||
DCERROR_INVALID_STATUS,
|
||||
DCERROR_UNNECCESSARY_COPY,
|
||||
DCERROR_SHOULDVE_DETACHED,
|
||||
DCERROR_SHOULDVE_DELETED,
|
||||
DCERROR_MISSING_DISPATCH_FUNCTION,
|
||||
DCERROR_WMI_IRP_NOT_FORWARDED,
|
||||
DCERROR_DELETED_PRESENT_PDO,
|
||||
DCERROR_BUS_FILTER_ERRONEOUSLY_DETACHED,
|
||||
DCERROR_BUS_FILTER_ERRONEOUSLY_DELETED,
|
||||
DCERROR_INCONSISTANT_STATUS,
|
||||
DCERROR_UNINITIALIZED_STATUS,
|
||||
DCERROR_IRP_RETURNED_WITHOUT_COMPLETION,
|
||||
DCERROR_COMPLETION_ROUTINE_PAGABLE,
|
||||
DCERROR_PENDING_BIT_NOT_MIGRATED,
|
||||
DCERROR_CANCELROUTINE_ON_FORWARDED_IRP,
|
||||
DCERROR_PNP_IRP_NEEDS_PDO_HANDLING,
|
||||
DCERROR_TARGET_RELATION_LIST_EMPTY,
|
||||
DCERROR_TARGET_RELATION_NEEDS_REF,
|
||||
DCERROR_BOGUS_PNP_IRP_COMPLETED,
|
||||
DCERROR_SUCCESSFUL_PNP_IRP_NOT_FORWARDED,
|
||||
DCERROR_UNTOUCHED_PNP_IRP_NOT_FORWARDED,
|
||||
DCERROR_BOGUS_POWER_IRP_COMPLETED,
|
||||
DCERROR_SUCCESSFUL_POWER_IRP_NOT_FORWARDED,
|
||||
DCERROR_UNTOUCHED_POWER_IRP_NOT_FORWARDED,
|
||||
DCERROR_PNP_QUERY_CAP_BAD_VERSION,
|
||||
DCERROR_PNP_QUERY_CAP_BAD_SIZE,
|
||||
DCERROR_PNP_QUERY_CAP_BAD_ADDRESS,
|
||||
DCERROR_PNP_QUERY_CAP_BAD_UI_NUM,
|
||||
DCERROR_RESTRICTED_IRP,
|
||||
DCERROR_REINIT_OF_ALLOCATED_IRP_WITHOUT_QUOTA,
|
||||
DCERROR_UNFORWARDED_IRP_COMPLETED,
|
||||
DCERROR_DISPATCH_CALLED_AT_BAD_IRQL,
|
||||
DCERROR_BOGUS_MINOR_STATUS_TRASHED,
|
||||
DCERROR_CANCELROUTINE_AFTER_COMPLETION,
|
||||
DCERROR_PENDING_RETURNED_NOT_MARKED,
|
||||
DCERROR_PENDING_MARKED_NOT_RETURNED,
|
||||
DCERROR_POWER_PAGABLE_NOT_INHERITED,
|
||||
DCERROR_DOUBLE_DELETION,
|
||||
DCERROR_DETACHED_IN_SURPRISE_REMOVAL,
|
||||
DCERROR_DELETED_IN_SURPRISE_REMOVAL,
|
||||
DCERROR_DO_INITIALIZING_NOT_CLEARED,
|
||||
DCERROR_DO_FLAG_NOT_COPIED,
|
||||
DCERROR_INCONSISTANT_DO_FLAGS,
|
||||
DCERROR_DEVICE_TYPE_NOT_COPIED,
|
||||
DCERROR_NON_FAILABLE_IRP,
|
||||
DCERROR_NON_PDO_RETURNED_IN_RELATION,
|
||||
DCERROR_DUPLICATE_ENUMERATION,
|
||||
DCERROR_FILE_IO_AT_BAD_IRQL,
|
||||
DCERROR_MISHANDLED_TARGET_DEVICE_RELATIONS,
|
||||
DCERROR_PENDING_RETURNED_NOT_MARKED_2,
|
||||
DCERROR_DDI_REQUIRES_PDO,
|
||||
DCERROR_MAXIMUM
|
||||
|
||||
} DCERROR_ID;
|
||||
|
||||
158
base/ntos/VERIFIER/vfpacket.h
Normal file
158
base/ntos/VERIFIER/vfpacket.h
Normal file
@ -0,0 +1,158 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
vfpacket.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This header exposes functions used to manage the verifier packet data that
|
||||
tracks IRPs.
|
||||
|
||||
--*/
|
||||
|
||||
|
||||
//
|
||||
// Currently, ntddk.h uses up to 0x2000 for Irp->Flags
|
||||
//
|
||||
#define IRPFLAG_EXAMINE_MASK 0xC0000000
|
||||
#define IRPFLAG_EXAMINE_NOT_TRACKED 0x80000000
|
||||
#define IRPFLAG_EXAMINE_TRACKED 0x40000000
|
||||
#define IRPFLAG_EXAMINE_UNMARKED 0x00000000
|
||||
|
||||
#define TRACKFLAG_ACTIVE 0x00000001
|
||||
#define IRP_ALLOC_COUNT 8
|
||||
|
||||
#define IRP_LOG_ENTRIES 16
|
||||
|
||||
typedef enum {
|
||||
|
||||
IOV_EVENT_NONE = 0,
|
||||
IOV_EVENT_IO_ALLOCATE_IRP,
|
||||
IOV_EVENT_IO_CALL_DRIVER,
|
||||
IOV_EVENT_IO_CALL_DRIVER_UNWIND,
|
||||
IOV_EVENT_IO_COMPLETE_REQUEST,
|
||||
IOV_EVENT_IO_COMPLETION_ROUTINE,
|
||||
IOV_EVENT_IO_COMPLETION_ROUTINE_UNWIND,
|
||||
IOV_EVENT_IO_CANCEL_IRP,
|
||||
IOV_EVENT_IO_FREE_IRP
|
||||
|
||||
} IOV_LOG_EVENT;
|
||||
|
||||
typedef struct {
|
||||
|
||||
IOV_LOG_EVENT Event;
|
||||
PETHREAD Thread;
|
||||
PVOID Address;
|
||||
ULONG_PTR Data;
|
||||
LARGE_INTEGER TimeStamp;
|
||||
|
||||
} IOV_LOG_ENTRY, *PIOV_LOG_ENTRY;
|
||||
|
||||
struct _IOV_SESSION_DATA;
|
||||
struct _IOV_REQUEST_PACKET;
|
||||
|
||||
typedef struct _IOV_SESSION_DATA *PIOV_SESSION_DATA;
|
||||
typedef struct _IOV_REQUEST_PACKET *PIOV_REQUEST_PACKET;
|
||||
|
||||
typedef struct _IOV_REQUEST_PACKET {
|
||||
|
||||
IOV_DATABASE_HEADER;
|
||||
ULONG Flags;
|
||||
KIRQL DepartureIrql; // Irql IRP will be dispatched at.
|
||||
KIRQL ArrivalIrql; // Irql IRP was sent in at.
|
||||
LIST_ENTRY SessionHead; // List of all sessions.
|
||||
CCHAR StackCount; // StackCount of tracked IRP.
|
||||
ULONG QuotaCharge; // Quota charged against IRP.
|
||||
PEPROCESS QuotaProcess; // Process quota was charged to.
|
||||
|
||||
PIO_COMPLETION_ROUTINE RealIrpCompletionRoutine;
|
||||
UCHAR RealIrpControl;
|
||||
PVOID RealIrpContext;
|
||||
PVOID AllocatorStack[IRP_ALLOC_COUNT];
|
||||
|
||||
//
|
||||
// The following information is for the assertion routines to read.
|
||||
//
|
||||
UCHAR TopStackLocation;
|
||||
|
||||
CCHAR PriorityBoost; // Boost from IofCompleteRequest
|
||||
UCHAR LastLocation; // Last location from IofCallDriver
|
||||
ULONG RefTrackingCount;
|
||||
|
||||
//
|
||||
// This field is only set on surrogate IRPs, and contains the locked system
|
||||
// VA for the destination of a direct I/O IRP that's being buffered.
|
||||
//
|
||||
PUCHAR SystemDestVA;
|
||||
|
||||
#if DBG
|
||||
IOV_LOG_ENTRY LogEntries[IRP_LOG_ENTRIES];
|
||||
ULONG LogEntryHead;
|
||||
ULONG LogEntryTail;
|
||||
#endif
|
||||
|
||||
PVERIFIER_SETTINGS_SNAPSHOT VerifierSettings;
|
||||
PIOV_SESSION_DATA pIovSessionData;
|
||||
|
||||
} IOV_REQUEST_PACKET;
|
||||
|
||||
PIOV_REQUEST_PACKET
|
||||
FASTCALL
|
||||
VfPacketCreateAndLock(
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
PIOV_REQUEST_PACKET
|
||||
FASTCALL
|
||||
VfPacketFindAndLock(
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfPacketAcquireLock(
|
||||
IN PIOV_REQUEST_PACKET IrpTrackingData
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfPacketReleaseLock(
|
||||
IN PIOV_REQUEST_PACKET IrpTrackingData
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfPacketReference(
|
||||
IN PIOV_REQUEST_PACKET IovPacket,
|
||||
IN IOV_REFERENCE_TYPE IovRefType
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfPacketDereference(
|
||||
IN PIOV_REQUEST_PACKET IovPacket,
|
||||
IN IOV_REFERENCE_TYPE IovRefType
|
||||
);
|
||||
|
||||
PIOV_SESSION_DATA
|
||||
FASTCALL
|
||||
VfPacketGetCurrentSessionData(
|
||||
IN PIOV_REQUEST_PACKET IovPacket
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfPacketLogEntry(
|
||||
IN PIOV_REQUEST_PACKET IovPacket,
|
||||
IN IOV_LOG_EVENT IovLogEvent,
|
||||
IN PVOID Address,
|
||||
IN ULONG_PTR Data
|
||||
);
|
||||
|
||||
84
base/ntos/VERIFIER/vfpnp.h
Normal file
84
base/ntos/VERIFIER/vfpnp.h
Normal file
@ -0,0 +1,84 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
vfpnp.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This header contains prototypes for verifying Pnp IRPs are handled
|
||||
correctly.
|
||||
|
||||
--*/
|
||||
|
||||
VOID
|
||||
VfPnpInit(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfPnpVerifyNewRequest(
|
||||
IN PIOV_REQUEST_PACKET IovPacket,
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIO_STACK_LOCATION IrpLastSp OPTIONAL,
|
||||
IN PIO_STACK_LOCATION IrpSp,
|
||||
IN PIOV_STACK_LOCATION StackLocationData,
|
||||
IN PVOID CallerAddress OPTIONAL
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfPnpVerifyIrpStackDownward(
|
||||
IN PIOV_REQUEST_PACKET IovPacket,
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIO_STACK_LOCATION IrpLastSp OPTIONAL,
|
||||
IN PIO_STACK_LOCATION IrpSp,
|
||||
IN PIOV_STACK_LOCATION RequestHeadLocationData,
|
||||
IN PIOV_STACK_LOCATION StackLocationData,
|
||||
IN PVOID CallerAddress OPTIONAL
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfPnpVerifyIrpStackUpward(
|
||||
IN PIOV_REQUEST_PACKET IovPacket,
|
||||
IN PIO_STACK_LOCATION IrpSp,
|
||||
IN PIOV_STACK_LOCATION RequestHeadLocationData,
|
||||
IN PIOV_STACK_LOCATION StackLocationData,
|
||||
IN BOOLEAN IsNewlyCompleted,
|
||||
IN BOOLEAN RequestFinalized
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfPnpDumpIrpStack(
|
||||
IN PIO_STACK_LOCATION IrpSp
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
FASTCALL
|
||||
VfPnpIsSystemRestrictedIrp(
|
||||
IN PIO_STACK_LOCATION IrpSp
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
FASTCALL
|
||||
VfPnpAdvanceIrpStatus(
|
||||
IN PIO_STACK_LOCATION IrpSp,
|
||||
IN NTSTATUS OriginalStatus,
|
||||
IN OUT NTSTATUS *StatusToAdvance
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfPnpTestStartedPdoStack(
|
||||
IN PDEVICE_OBJECT PhysicalDeviceObject
|
||||
);
|
||||
|
||||
84
base/ntos/VERIFIER/vfpower.h
Normal file
84
base/ntos/VERIFIER/vfpower.h
Normal file
@ -0,0 +1,84 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
vfpower.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This header contains prototypes for verifying Power IRPs are handled
|
||||
correctly.
|
||||
|
||||
--*/
|
||||
|
||||
VOID
|
||||
VfPowerInit(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfPowerVerifyNewRequest(
|
||||
IN PIOV_REQUEST_PACKET IovPacket,
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIO_STACK_LOCATION IrpLastSp OPTIONAL,
|
||||
IN PIO_STACK_LOCATION IrpSp,
|
||||
IN PIOV_STACK_LOCATION StackLocationData,
|
||||
IN PVOID CallerAddress OPTIONAL
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfPowerVerifyIrpStackDownward(
|
||||
IN PIOV_REQUEST_PACKET IovPacket,
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIO_STACK_LOCATION IrpLastSp OPTIONAL,
|
||||
IN PIO_STACK_LOCATION IrpSp,
|
||||
IN PIOV_STACK_LOCATION RequestHeadLocationData,
|
||||
IN PIOV_STACK_LOCATION StackLocationData,
|
||||
IN PVOID CallerAddress OPTIONAL
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfPowerVerifyIrpStackUpward(
|
||||
IN PIOV_REQUEST_PACKET IovPacket,
|
||||
IN PIO_STACK_LOCATION IrpSp,
|
||||
IN PIOV_STACK_LOCATION RequestHeadLocationData,
|
||||
IN PIOV_STACK_LOCATION StackLocationData,
|
||||
IN BOOLEAN IsNewlyCompleted,
|
||||
IN BOOLEAN RequestFinalized
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfPowerDumpIrpStack(
|
||||
IN PIO_STACK_LOCATION IrpSp
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
FASTCALL
|
||||
VfPowerIsSystemRestrictedIrp(
|
||||
IN PIO_STACK_LOCATION IrpSp
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
FASTCALL
|
||||
VfPowerAdvanceIrpStatus(
|
||||
IN PIO_STACK_LOCATION IrpSp,
|
||||
IN NTSTATUS OriginalStatus,
|
||||
IN OUT NTSTATUS *StatusToAdvance
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfPowerTestStartedPdoStack(
|
||||
IN PDEVICE_OBJECT PhysicalDeviceObject
|
||||
);
|
||||
|
||||
32
base/ntos/VERIFIER/vfpragma.h
Normal file
32
base/ntos/VERIFIER/vfpragma.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
vfpragma.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This header contains disable instructions for W4 warnings generated
|
||||
by public headers. This way we can still compile modules at W4.
|
||||
|
||||
--*/
|
||||
|
||||
//
|
||||
// Disable W4 level warnings generated by public headers.
|
||||
//
|
||||
|
||||
#pragma warning(disable:4214) // bit field types other than int
|
||||
#pragma warning(disable:4201) // nameless struct/union
|
||||
#pragma warning(disable:4324) // alignment sensitive to declspec
|
||||
#pragma warning(disable:4127) // condition expression is constant
|
||||
#pragma warning(disable:4115) // named type definition in parentheses
|
||||
#pragma warning(disable:4232) // dllimport not static
|
||||
#pragma warning(disable:4206) // translation unit empty
|
||||
#pragma warning(disable:4054) // function pointer to data pointer cast
|
||||
|
||||
29
base/ntos/VERIFIER/vfprint.h
Normal file
29
base/ntos/VERIFIER/vfprint.h
Normal file
@ -0,0 +1,29 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
vfprint.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This header exposes prototypes required when outputting various data types
|
||||
to the debugger.
|
||||
|
||||
--*/
|
||||
|
||||
VOID
|
||||
VfPrintDumpIrpStack(
|
||||
IN PIO_STACK_LOCATION IrpSp
|
||||
);
|
||||
|
||||
VOID
|
||||
VfPrintDumpIrp(
|
||||
IN PIRP IrpToFlag
|
||||
);
|
||||
|
||||
31
base/ntos/VERIFIER/vfrandom.h
Normal file
31
base/ntos/VERIFIER/vfrandom.h
Normal file
@ -0,0 +1,31 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
vfrandom.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This header exposes support for random number generation as needed by the
|
||||
verifier.
|
||||
|
||||
--*/
|
||||
|
||||
VOID
|
||||
VfRandomInit(
|
||||
VOID
|
||||
);
|
||||
|
||||
ULONG
|
||||
FASTCALL
|
||||
VfRandomGetNumber(
|
||||
IN ULONG Minimum,
|
||||
IN ULONG Maximum
|
||||
);
|
||||
|
||||
316
base/ntos/VERIFIER/vfsettings.h
Normal file
316
base/ntos/VERIFIER/vfsettings.h
Normal file
@ -0,0 +1,316 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
vfsettings.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This header contains prototypes for manipulating verifier options and
|
||||
values.
|
||||
|
||||
--*/
|
||||
|
||||
typedef PVOID PVERIFIER_SETTINGS_SNAPSHOT;
|
||||
|
||||
typedef enum {
|
||||
|
||||
//
|
||||
// This option lets the verifer begin tracking all IRPs. It must be enabled
|
||||
// for most of the other IRP verification options to work.
|
||||
//
|
||||
VERIFIER_OPTION_TRACK_IRPS = 1,
|
||||
|
||||
//
|
||||
// This option forces all IRPs to be allocated from the special pool.
|
||||
// VERIFIER_OPTION_TRACK_IRPS need not be enabled.
|
||||
//
|
||||
VERIFIER_OPTION_MONITOR_IRP_ALLOCS,
|
||||
|
||||
//
|
||||
// This option enables various checks for basic/common IRP handling mistakes.
|
||||
//
|
||||
VERIFIER_OPTION_POLICE_IRPS,
|
||||
|
||||
//
|
||||
// This option enables checks specific to major/minor codes.
|
||||
//
|
||||
VERIFIER_OPTION_MONITOR_MAJORS,
|
||||
|
||||
//
|
||||
// This option causes the call stacks of IRP dispatch and completion
|
||||
// routines to be seeded with 0xFFFFFFFF. This value is illegal for a
|
||||
// status code, and such seeding flushes out uninitialized variable bugs.
|
||||
//
|
||||
VERIFIER_OPTION_SEEDSTACK,
|
||||
|
||||
//
|
||||
// This option sends a bogus QueryDeviceRelations IRP to newly built stacks.
|
||||
// The particular IRP sent is of type -1, and has a -1 passed in for the
|
||||
// device list.
|
||||
//
|
||||
VERIFIER_OPTION_RELATION_IGNORANCE_TEST,
|
||||
|
||||
//
|
||||
// This option causes the verifier to stop on unnecessary IRP stack copies.
|
||||
// It is useful for optimizing drivers.
|
||||
//
|
||||
VERIFIER_OPTION_FLAG_UNNECCESSARY_COPIES,
|
||||
|
||||
VERIFIER_OPTION_SEND_BOGUS_WMI_IRPS,
|
||||
VERIFIER_OPTION_SEND_BOGUS_POWER_IRPS,
|
||||
|
||||
//
|
||||
// If this option is enabled, the verifier makes sure drivers mark the IRP
|
||||
// pending if and only if STATUS_PENDING is returned, and visa versa.
|
||||
//
|
||||
VERIFIER_OPTION_MONITOR_PENDING_IO,
|
||||
|
||||
//
|
||||
// If this option is enabled, the verifier makes all IRPs return in an
|
||||
// asynchronous manner. Specifically, all IRPs are marked pending, and
|
||||
// STATUS_PENDING is returned from every IoCallDriver.
|
||||
//
|
||||
VERIFIER_OPTION_FORCE_PENDING,
|
||||
|
||||
//
|
||||
// If this option is enabled, the verifier will change the status code of
|
||||
// successful IRPs to alternate success status's. This catches many IRP
|
||||
// forwarding bugs.
|
||||
//
|
||||
VERIFIER_OPTION_ROTATE_STATUS,
|
||||
|
||||
//
|
||||
// If this option is enabled, the verifier will undo the effects of
|
||||
// IoSkipCurrentIrpStackLocation so that all stacks appear to be copied.
|
||||
// (Exempting the case where an IRP was forwarded to another stack)
|
||||
//
|
||||
VERIFIER_OPTION_CONSUME_ALWAYS,
|
||||
|
||||
//
|
||||
// If this option is enabled, the verifier will update SRB's to handle
|
||||
// surrogate IRPs. Some SCSI IRPs can't be surrogated unless the
|
||||
// SRB->OriginalRequest pointer is updated. This is due to a busted SRB
|
||||
// architecture. Note that the technique used to identify an SRB IRP is
|
||||
// "fuzzy", and could in theory touch an IRP it shouldn't have!
|
||||
//
|
||||
VERIFIER_OPTION_SMASH_SRBS,
|
||||
|
||||
//
|
||||
// If this option is enabled, the verifier will replace original IRPs with
|
||||
// surrogates when traveling down the stack. The surrogates are allocated
|
||||
// from special pool, and get freed immediately upon completion. This lets
|
||||
// the verifier catch drivers that touch IRPs after they're completed.
|
||||
//
|
||||
VERIFIER_OPTION_SURROGATE_IRPS,
|
||||
|
||||
//
|
||||
// If this option is enabled, the verifier buffers all direct I/O. It does
|
||||
// this by allocating an alternate MDL and copying the MDL contents back
|
||||
// to user mode only after IRP completion. This allows overruns, underruns,
|
||||
// and late accesses to be detected.
|
||||
//
|
||||
VERIFIER_OPTION_BUFFER_DIRECT_IO,
|
||||
|
||||
//
|
||||
// If this option is enabled, the verifier delays completion of all IRPs
|
||||
// via timer. VERIFIER_OPTION_FORCE_PENDING is set by inference.
|
||||
//
|
||||
VERIFIER_OPTION_DEFER_COMPLETION,
|
||||
|
||||
//
|
||||
// If this option is enabled, the verifier completes every IRP at
|
||||
// PASSIVE_LEVEL, regardless of major function.
|
||||
// VERIFIER_OPTION_FORCE_PENDING is set by inference.
|
||||
//
|
||||
VERIFIER_OPTION_COMPLETE_AT_PASSIVE,
|
||||
|
||||
//
|
||||
// If this option is enabled, the verifier completes every IRP at
|
||||
// DISPATCH_LEVEL, regardless of major function.
|
||||
//
|
||||
VERIFIER_OPTION_COMPLETE_AT_DISPATCH,
|
||||
|
||||
//
|
||||
// If this option is enabled, the verifier monitors cancel routines to make
|
||||
// sure they are cleared appropriately.
|
||||
//
|
||||
VERIFIER_OPTION_VERIFY_CANCEL_LOGIC,
|
||||
|
||||
VERIFIER_OPTION_RANDOMLY_CANCEL_IRPS,
|
||||
|
||||
//
|
||||
// If this option is enabled, the verifier inserts filter device objects
|
||||
// into WDM stacks to ensure IRPs are properly forwarded.
|
||||
//
|
||||
VERIFIER_OPTION_INSERT_WDM_FILTERS,
|
||||
|
||||
//
|
||||
// If this option is enabled, the verifier monitors drivers to ensure they
|
||||
// don't send system reserved IRPs to WDM stacks.
|
||||
//
|
||||
VERIFIER_OPTION_PROTECT_RESERVED_IRPS,
|
||||
|
||||
//
|
||||
// If this option is enabled, the verifier walks the entire stack to ensure
|
||||
// the DO bits are properly built during AddDevice. This includes the
|
||||
// DO_POWER_PAGABLE flag.
|
||||
//
|
||||
VERIFIER_OPTION_VERIFY_DO_FLAGS,
|
||||
|
||||
//
|
||||
// If this option is enabled, the verifier watches Target device relation
|
||||
// IRPs to make sure the device object is properly reference counted.
|
||||
//
|
||||
VERIFIER_OPTION_TEST_TARGET_REFCOUNT,
|
||||
|
||||
//
|
||||
// Lets you detect when deadlocks can occur
|
||||
//
|
||||
VERIFIER_OPTION_DETECT_DEADLOCKS,
|
||||
|
||||
//
|
||||
// If this option is enabled, all dma operations will be hooked and
|
||||
// validated.
|
||||
//
|
||||
VERIFIER_OPTION_VERIFY_DMA,
|
||||
|
||||
//
|
||||
// This option double buffers all dma and erects guard pages on each side
|
||||
// of all common buffers and mapped buffers. Is memory-intensive but can
|
||||
// catch hardware buffer overruns and drivers that don't flush adapter
|
||||
// buffers.
|
||||
//
|
||||
VERIFIER_OPTION_DOUBLE_BUFFER_DMA,
|
||||
|
||||
//
|
||||
// If this option is enabled, you get notified when the performance counter
|
||||
// is being naughty
|
||||
//
|
||||
VERIFIER_OPTION_VERIFY_PERFORMANCE_COUNTER,
|
||||
|
||||
//
|
||||
// If this option is enabled, the verifier checks for implementations of
|
||||
// IRP_MN_DEVICE_USAGE_NOTIFICATION and IRP_MN_SURPRISE_REMOVAL. The
|
||||
// verifier will also make sure PnP Cancel IRPs are not explicitely failed.
|
||||
//
|
||||
VERIFIER_OPTION_EXTENDED_REQUIRED_IRPS,
|
||||
|
||||
//
|
||||
// If this option is enabled, the verifier mixes up device relations
|
||||
// to ensure drivers aren't depending on ordering.
|
||||
//
|
||||
VERIFIER_OPTION_SCRAMBLE_RELATIONS,
|
||||
|
||||
//
|
||||
// If this option is enabled, the verifier ensures proper detaching and
|
||||
// deletion occurs on removes and surprise removes.
|
||||
//
|
||||
VERIFIER_OPTION_MONITOR_REMOVES,
|
||||
|
||||
//
|
||||
// If this option is enabled, the verifier ensures device relations only
|
||||
// consist of PDO's.
|
||||
//
|
||||
VERIFIER_OPTION_EXAMINE_RELATION_PDOS,
|
||||
|
||||
//
|
||||
// If this option is enabled, the verifier enabled hardware verification
|
||||
// (bus specific behavior)
|
||||
//
|
||||
VERIFIER_OPTION_HARDWARE_VERIFICATION,
|
||||
|
||||
//
|
||||
// If this option is enabled, the verifier ensures system BIOS verification
|
||||
//
|
||||
VERIFIER_OPTION_SYSTEM_BIOS_VERIFICATION,
|
||||
|
||||
//
|
||||
// If this option is enabled, the verifier exposes IRP history data that
|
||||
// can be used to test for security holes.
|
||||
//
|
||||
VERIFIER_OPTION_EXPOSE_IRP_HISTORY,
|
||||
|
||||
VERIFIER_OPTION_MAX
|
||||
|
||||
} VERIFIER_OPTION;
|
||||
|
||||
typedef enum {
|
||||
|
||||
//
|
||||
// If VERIFIER_OPTION_DEFER_COMPLETION is set, this value contains the time
|
||||
// an IRP will be deferred, in 100us units.
|
||||
//
|
||||
VERIFIER_VALUE_IRP_DEFERRAL_TIME = 1,
|
||||
|
||||
//
|
||||
// This shall be the percentage of allocates to fail during low resource
|
||||
// simulation.
|
||||
//
|
||||
VERIFIER_VALUE_LOW_RESOURCE_PERCENTAGE,
|
||||
|
||||
//
|
||||
// If VERIFIER_OPTION_EXPOSE_IRP_HISTORY is set, this value contains the
|
||||
// amount of IRPs per device object to log.
|
||||
//
|
||||
VERIFIER_VALUE_IRPLOG_COUNT,
|
||||
|
||||
VERIFIER_VALUE_MAX
|
||||
|
||||
} VERIFIER_VALUE;
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfSettingsInit(
|
||||
IN ULONG MmFlags
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
FASTCALL
|
||||
VfSettingsIsOptionEnabled(
|
||||
IN PVERIFIER_SETTINGS_SNAPSHOT VerifierSettingsSnapshot OPTIONAL,
|
||||
IN VERIFIER_OPTION VerifierOption
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfSettingsCreateSnapshot(
|
||||
IN OUT PVERIFIER_SETTINGS_SNAPSHOT VerifierSettingsSnapshot
|
||||
);
|
||||
|
||||
ULONG
|
||||
FASTCALL
|
||||
VfSettingsGetSnapshotSize(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfSettingsSetOption(
|
||||
IN PVERIFIER_SETTINGS_SNAPSHOT VerifierSettingsSnapshot OPTIONAL,
|
||||
IN VERIFIER_OPTION VerifierOption,
|
||||
IN BOOLEAN Setting
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfSettingsGetValue(
|
||||
IN PVERIFIER_SETTINGS_SNAPSHOT VerifierSettingsSnapshot OPTIONAL,
|
||||
IN VERIFIER_VALUE VerifierValue,
|
||||
OUT ULONG *Value
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfSettingsSetValue(
|
||||
IN PVERIFIER_SETTINGS_SNAPSHOT VerifierSettingsSnapshot OPTIONAL,
|
||||
IN VERIFIER_VALUE VerifierValue,
|
||||
IN ULONG Value
|
||||
);
|
||||
|
||||
25
base/ntos/VERIFIER/vfstack.h
Normal file
25
base/ntos/VERIFIER/vfstack.h
Normal file
@ -0,0 +1,25 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
vfstack.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This header contains prototypes for verifying drivers don't improperly use
|
||||
thread stacks.
|
||||
|
||||
--*/
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfStackSeedStack(
|
||||
IN ULONG Seed
|
||||
);
|
||||
|
||||
23
base/ntos/VERIFIER/vftriage.h
Normal file
23
base/ntos/VERIFIER/vftriage.h
Normal file
@ -0,0 +1,23 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
vftriage
|
||||
|
||||
Abstract:
|
||||
|
||||
Code to support driver verifier triage decisions and running mode.
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef INCLUDED_VFTRIAGE_H
|
||||
#define INCLUDED_VFTRIAGE_H
|
||||
|
||||
#endif // #ifndef INCLUDED_VFTRIAGE_H
|
||||
|
||||
38
base/ntos/VERIFIER/vfutil.h
Normal file
38
base/ntos/VERIFIER/vfutil.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
vfutil.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This header contains prototypes for various functions required to do driver
|
||||
verification.
|
||||
|
||||
--*/
|
||||
|
||||
typedef enum {
|
||||
|
||||
VFMP_INSTANT = 0,
|
||||
VFMP_INSTANT_NONPAGED
|
||||
|
||||
} MEMORY_PERSISTANCE;
|
||||
|
||||
BOOLEAN
|
||||
VfUtilIsMemoryRangeReadable(
|
||||
IN PVOID Location,
|
||||
IN size_t Length,
|
||||
IN MEMORY_PERSISTANCE Persistance
|
||||
);
|
||||
|
||||
VOID
|
||||
VfSetVerifierEnabled (
|
||||
LOGICAL Value
|
||||
);
|
||||
|
||||
70
base/ntos/VERIFIER/vfwmi.h
Normal file
70
base/ntos/VERIFIER/vfwmi.h
Normal file
@ -0,0 +1,70 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
vfwmi.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This header contains prototypes for verifying System Control IRPs are
|
||||
handled correctly.
|
||||
|
||||
--*/
|
||||
|
||||
VOID
|
||||
VfWmiInit(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfWmiVerifyNewRequest(
|
||||
IN PIOV_REQUEST_PACKET IovPacket,
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIO_STACK_LOCATION IrpLastSp OPTIONAL,
|
||||
IN PIO_STACK_LOCATION IrpSp,
|
||||
IN PIOV_STACK_LOCATION StackLocationData,
|
||||
IN PVOID CallerAddress OPTIONAL
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfWmiVerifyIrpStackDownward(
|
||||
IN PIOV_REQUEST_PACKET IovPacket,
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIO_STACK_LOCATION IrpLastSp OPTIONAL,
|
||||
IN PIO_STACK_LOCATION IrpSp,
|
||||
IN PIOV_STACK_LOCATION RequestHeadLocationData,
|
||||
IN PIOV_STACK_LOCATION StackLocationData,
|
||||
IN PVOID CallerAddress OPTIONAL
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfWmiVerifyIrpStackUpward(
|
||||
IN PIOV_REQUEST_PACKET IovPacket,
|
||||
IN PIO_STACK_LOCATION IrpSp,
|
||||
IN PIOV_STACK_LOCATION RequestHeadLocationData,
|
||||
IN PIOV_STACK_LOCATION StackLocationData,
|
||||
IN BOOLEAN IsNewlyCompleted,
|
||||
IN BOOLEAN RequestFinalized
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfWmiDumpIrpStack(
|
||||
IN PIO_STACK_LOCATION IrpSp
|
||||
);
|
||||
|
||||
VOID
|
||||
FASTCALL
|
||||
VfWmiTestStartedPdoStack(
|
||||
IN PDEVICE_OBJECT PhysicalDeviceObject
|
||||
);
|
||||
|
||||
1105
base/ntos/VERIFIER/vfzwapi.h
Normal file
1105
base/ntos/VERIFIER/vfzwapi.h
Normal file
File diff suppressed because it is too large
Load Diff
26
base/ntos/cache/BUILD/makefile
vendored
Normal file
26
base/ntos/cache/BUILD/makefile
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
#
|
||||
# You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
# If you do not agree to the terms, do not use the code.
|
||||
#
|
||||
|
||||
library = $(module)
|
||||
|
||||
asobjs=
|
||||
ccarchobjs=
|
||||
|
||||
ccobjs= \
|
||||
$(OBJ)\cachedat.obj \
|
||||
$(OBJ)\cachesub.obj \
|
||||
$(OBJ)\copysup.obj \
|
||||
$(OBJ)\fssup.obj \
|
||||
$(OBJ)\lazyrite.obj \
|
||||
$(OBJ)\logsup.obj \
|
||||
$(OBJ)\mdlsup.obj \
|
||||
$(OBJ)\pinsup.obj \
|
||||
$(OBJ)\ccperf.obj \
|
||||
$(OBJ)\vacbsup.obj
|
||||
|
||||
!include $(ntos)\BUILD\makefile.build
|
||||
|
||||
195
base/ntos/cache/cachedat.c
vendored
Normal file
195
base/ntos/cache/cachedat.c
vendored
Normal file
@ -0,0 +1,195 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
cachedat.c
|
||||
|
||||
Abstract:
|
||||
|
||||
This module implements the Memory Management based cache management
|
||||
routines for the common Cache subsystem.
|
||||
|
||||
--*/
|
||||
|
||||
#include "cc.h"
|
||||
|
||||
//
|
||||
// Global SharedCacheMap lists and resource to synchronize access to it.
|
||||
//
|
||||
//
|
||||
|
||||
// extern KSPIN_LOCK CcMasterSpinLock;
|
||||
LIST_ENTRY CcCleanSharedCacheMapList;
|
||||
SHARED_CACHE_MAP_LIST_CURSOR CcDirtySharedCacheMapList;
|
||||
SHARED_CACHE_MAP_LIST_CURSOR CcLazyWriterCursor;
|
||||
|
||||
//
|
||||
// Worker thread structures:
|
||||
//
|
||||
// A spinlock to synchronize all three lists.
|
||||
// A count of the number of worker threads Cc will use
|
||||
// A count of the number of worker threads Cc in use
|
||||
// A listhead for preinitialized executive work items for Cc use.
|
||||
// A listhead for an express queue of WORK_QUEUE_ENTRYs
|
||||
// A listhead for a regular queue of WORK_QUEUE_ENTRYs
|
||||
// A listhead for a post-tick queue of WORK_QUEUE_ENTRYs
|
||||
//
|
||||
// A flag indicating if we are throttling the queue to a single thread
|
||||
//
|
||||
|
||||
// extern KSPIN_LOCK CcWorkQueueSpinLock;
|
||||
ULONG CcNumberWorkerThreads = 0;
|
||||
ULONG CcNumberActiveWorkerThreads = 0;
|
||||
LIST_ENTRY CcIdleWorkerThreadList;
|
||||
LIST_ENTRY CcExpressWorkQueue;
|
||||
LIST_ENTRY CcRegularWorkQueue;
|
||||
LIST_ENTRY CcPostTickWorkQueue;
|
||||
|
||||
BOOLEAN CcQueueThrottle = FALSE;
|
||||
|
||||
//
|
||||
// Store the current idle delay and target time to clean all. We must calculate
|
||||
// the idle delay in terms of clock ticks for the lazy writer timeout.
|
||||
//
|
||||
|
||||
ULONG CcIdleDelayTick;
|
||||
LARGE_INTEGER CcNoDelay;
|
||||
LARGE_INTEGER CcFirstDelay = {(ULONG)-(3*LAZY_WRITER_IDLE_DELAY), -1};
|
||||
LARGE_INTEGER CcIdleDelay = {(ULONG)-LAZY_WRITER_IDLE_DELAY, -1};
|
||||
LARGE_INTEGER CcCollisionDelay = {(ULONG)-LAZY_WRITER_COLLISION_DELAY, -1};
|
||||
LARGE_INTEGER CcTargetCleanDelay = {(ULONG)-(LONG)(LAZY_WRITER_IDLE_DELAY * (LAZY_WRITER_MAX_AGE_TARGET + 1)), -1};
|
||||
|
||||
//
|
||||
// Spinlock for controlling access to Vacb and related global structures,
|
||||
// and a counter indicating how many Vcbs are active.
|
||||
//
|
||||
|
||||
// extern KSPIN_LOCK CcVacbSpinLock;
|
||||
ULONG_PTR CcNumberVacbs;
|
||||
|
||||
//
|
||||
// Pointer to the global Vacb vector.
|
||||
//
|
||||
|
||||
PVACB CcVacbs;
|
||||
PVACB CcBeyondVacbs;
|
||||
LIST_ENTRY CcVacbLru;
|
||||
LIST_ENTRY CcVacbFreeList;
|
||||
ULONG CcMaxVacbLevelsSeen = 1;
|
||||
ULONG CcVacbLevelEntries = 0;
|
||||
PVACB *CcVacbLevelFreeList = NULL;
|
||||
ULONG CcVacbLevelWithBcbsEntries = 0;
|
||||
PVACB *CcVacbLevelWithBcbsFreeList = NULL;
|
||||
|
||||
//
|
||||
// Deferred write list and respective Thresholds
|
||||
//
|
||||
|
||||
extern ALIGNED_SPINLOCK CcDeferredWriteSpinLock;
|
||||
LIST_ENTRY CcDeferredWrites;
|
||||
ULONG CcDirtyPageThreshold;
|
||||
ULONG CcDirtyPageTarget;
|
||||
ULONG CcPagesYetToWrite;
|
||||
ULONG CcPagesWrittenLastTime = 0;
|
||||
ULONG CcDirtyPagesLastScan = 0;
|
||||
ULONG CcAvailablePagesThreshold = 100;
|
||||
ULONG CcTotalDirtyPages = 0;
|
||||
|
||||
//
|
||||
// Captured system size
|
||||
//
|
||||
|
||||
MM_SYSTEMSIZE CcCapturedSystemSize;
|
||||
|
||||
//
|
||||
// Number of outstanding aggressive zeroers in the system. Used
|
||||
// to throttle the activity.
|
||||
//
|
||||
|
||||
LONG CcAggressiveZeroCount;
|
||||
LONG CcAggressiveZeroThreshold;
|
||||
|
||||
//
|
||||
// Tuning options du Jour
|
||||
//
|
||||
|
||||
ULONG CcTune = 0;
|
||||
|
||||
//
|
||||
// Global structure controlling lazy writer algorithms
|
||||
//
|
||||
|
||||
LAZY_WRITER LazyWriter;
|
||||
|
||||
GENERAL_LOOKASIDE CcTwilightLookasideList;
|
||||
|
||||
//
|
||||
// Global list of pinned Bcbs which may be examined for debug purposes
|
||||
//
|
||||
|
||||
#if DBG
|
||||
|
||||
ULONG CcBcbCount;
|
||||
LIST_ENTRY CcBcbList;
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
// Throw away miss counter.
|
||||
//
|
||||
|
||||
ULONG CcThrowAway;
|
||||
|
||||
//
|
||||
// Performance Counters
|
||||
//
|
||||
|
||||
ULONG CcFastReadNoWait;
|
||||
ULONG CcFastReadWait;
|
||||
ULONG CcFastReadResourceMiss;
|
||||
ULONG CcFastReadNotPossible;
|
||||
|
||||
ULONG CcFastMdlReadNoWait;
|
||||
ULONG CcFastMdlReadWait;
|
||||
ULONG CcFastMdlReadResourceMiss;
|
||||
ULONG CcFastMdlReadNotPossible;
|
||||
|
||||
ULONG CcMapDataNoWait;
|
||||
ULONG CcMapDataWait;
|
||||
ULONG CcMapDataNoWaitMiss;
|
||||
ULONG CcMapDataWaitMiss;
|
||||
|
||||
ULONG CcPinMappedDataCount;
|
||||
|
||||
ULONG CcPinReadNoWait;
|
||||
ULONG CcPinReadWait;
|
||||
ULONG CcPinReadNoWaitMiss;
|
||||
ULONG CcPinReadWaitMiss;
|
||||
|
||||
ULONG CcCopyReadNoWait;
|
||||
ULONG CcCopyReadWait;
|
||||
ULONG CcCopyReadNoWaitMiss;
|
||||
ULONG CcCopyReadWaitMiss;
|
||||
|
||||
ULONG CcMdlReadNoWait;
|
||||
ULONG CcMdlReadWait;
|
||||
ULONG CcMdlReadNoWaitMiss;
|
||||
ULONG CcMdlReadWaitMiss;
|
||||
|
||||
ULONG CcReadAheadIos;
|
||||
|
||||
ULONG CcLazyWriteHotSpots;
|
||||
ULONG CcLazyWriteIos;
|
||||
ULONG CcLazyWritePages;
|
||||
ULONG CcDataFlushes;
|
||||
ULONG CcDataPages;
|
||||
|
||||
ULONG CcLostDelayedWrites;
|
||||
|
||||
PULONG CcMissCounter = &CcThrowAway;
|
||||
6857
base/ntos/cache/cachesub.c
vendored
Normal file
6857
base/ntos/cache/cachesub.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2190
base/ntos/cache/cc.h
vendored
Normal file
2190
base/ntos/cache/cc.h
vendored
Normal file
File diff suppressed because it is too large
Load Diff
104
base/ntos/cache/ccperf.c
vendored
Normal file
104
base/ntos/cache/ccperf.c
vendored
Normal file
@ -0,0 +1,104 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
CcPerf.c
|
||||
|
||||
Abstract:
|
||||
|
||||
This module contains the perf trace routines in Cc Component
|
||||
|
||||
--*/
|
||||
|
||||
#include "cc.h"
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGEWMI, CcPerfFileRunDown)
|
||||
#endif //ALLOC_PRAGMA
|
||||
|
||||
VOID
|
||||
CcPerfFileRunDown(
|
||||
PPERFINFO_ENTRY_TABLE HashTable
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine walks the following lists:
|
||||
|
||||
1. CcDirtySharedCacheMapList
|
||||
2. CcCleanSharedCacheMapList
|
||||
|
||||
and returns a pointer to a pool allocation
|
||||
containing the referenced file object pointers.
|
||||
|
||||
Arguments:
|
||||
|
||||
None.
|
||||
|
||||
Return Value:
|
||||
|
||||
Returns a pointer to a NULL terminated pool allocation
|
||||
containing the file object pointers from the two lists,
|
||||
NULL if the memory could not be allocated.
|
||||
|
||||
It is also the responsibility of the caller to dereference each
|
||||
file object in the list and then free the returned pool.
|
||||
|
||||
Environment:
|
||||
|
||||
PASSIVE_LEVEL, arbitrary thread context.
|
||||
--*/
|
||||
{
|
||||
KIRQL OldIrql;
|
||||
PSHARED_CACHE_MAP SharedCacheMap;
|
||||
|
||||
ASSERT (KeGetCurrentIrql () == PASSIVE_LEVEL);
|
||||
|
||||
CcAcquireMasterLock( &OldIrql );
|
||||
|
||||
//
|
||||
// Walk through CcDirtySharedCacheMapList
|
||||
//
|
||||
|
||||
SharedCacheMap = CONTAINING_RECORD( CcDirtySharedCacheMapList.SharedCacheMapLinks.Flink,
|
||||
SHARED_CACHE_MAP,
|
||||
SharedCacheMapLinks );
|
||||
|
||||
while (&SharedCacheMap->SharedCacheMapLinks != &CcDirtySharedCacheMapList.SharedCacheMapLinks) {
|
||||
//
|
||||
// Skip over cursors
|
||||
//
|
||||
if (!FlagOn(SharedCacheMap->Flags, IS_CURSOR)) {
|
||||
PerfInfoAddToFileHash(HashTable, SharedCacheMap->FileObject);
|
||||
}
|
||||
SharedCacheMap = CONTAINING_RECORD( SharedCacheMap->SharedCacheMapLinks.Flink,
|
||||
SHARED_CACHE_MAP,
|
||||
SharedCacheMapLinks );
|
||||
}
|
||||
|
||||
//
|
||||
// CcCleanSharedCacheMapList
|
||||
//
|
||||
SharedCacheMap = CONTAINING_RECORD( CcCleanSharedCacheMapList.Flink,
|
||||
SHARED_CACHE_MAP,
|
||||
SharedCacheMapLinks );
|
||||
|
||||
while (&SharedCacheMap->SharedCacheMapLinks != &CcCleanSharedCacheMapList) {
|
||||
PerfInfoAddToFileHash(HashTable, SharedCacheMap->FileObject);
|
||||
|
||||
SharedCacheMap = CONTAINING_RECORD( SharedCacheMap->SharedCacheMapLinks.Flink,
|
||||
SHARED_CACHE_MAP,
|
||||
SharedCacheMapLinks );
|
||||
|
||||
}
|
||||
|
||||
CcReleaseMasterLock( OldIrql );
|
||||
return;
|
||||
}
|
||||
2175
base/ntos/cache/copysup.c
vendored
Normal file
2175
base/ntos/cache/copysup.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4000
base/ntos/cache/fssup.c
vendored
Normal file
4000
base/ntos/cache/fssup.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1056
base/ntos/cache/lazyrite.c
vendored
Normal file
1056
base/ntos/cache/lazyrite.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
699
base/ntos/cache/logsup.c
vendored
Normal file
699
base/ntos/cache/logsup.c
vendored
Normal file
@ -0,0 +1,699 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
logsup.c
|
||||
|
||||
Abstract:
|
||||
|
||||
This module implements the special cache manager support for logging
|
||||
file systems.
|
||||
|
||||
--*/
|
||||
|
||||
#include "cc.h"
|
||||
|
||||
//
|
||||
// Define our debug constant
|
||||
//
|
||||
|
||||
#define me 0x0000040
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE,CcSetLogHandleForFile)
|
||||
#endif
|
||||
|
||||
|
||||
VOID
|
||||
CcSetAdditionalCacheAttributes (
|
||||
__in PFILE_OBJECT FileObject,
|
||||
__in BOOLEAN DisableReadAhead,
|
||||
__in BOOLEAN DisableWriteBehind
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine supports the setting of disable read ahead or disable write
|
||||
behind flags to control Cache Manager operation. This routine may be
|
||||
called any time after calling CcInitializeCacheMap. Initially both
|
||||
read ahead and write behind are enabled. Note that the state of both
|
||||
of these flags must be specified on each call to this routine.
|
||||
|
||||
Arguments:
|
||||
|
||||
FileObject - File object for which the respective flags are to be set.
|
||||
|
||||
DisableReadAhead - FALSE to enable read ahead, TRUE to disable it.
|
||||
|
||||
DisableWriteBehind - FALSE to enable write behind, TRUE to disable it.
|
||||
|
||||
Return Value:
|
||||
|
||||
None.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
PSHARED_CACHE_MAP SharedCacheMap;
|
||||
KIRQL OldIrql;
|
||||
|
||||
//
|
||||
// Get pointer to SharedCacheMap.
|
||||
//
|
||||
|
||||
SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
|
||||
|
||||
//
|
||||
// Now set the flags and return.
|
||||
//
|
||||
|
||||
CcAcquireMasterLock( &OldIrql );
|
||||
if (DisableReadAhead) {
|
||||
SetFlag(SharedCacheMap->Flags, DISABLE_READ_AHEAD);
|
||||
} else {
|
||||
ClearFlag(SharedCacheMap->Flags, DISABLE_READ_AHEAD);
|
||||
}
|
||||
if (DisableWriteBehind) {
|
||||
SetFlag(SharedCacheMap->Flags, DISABLE_WRITE_BEHIND | MODIFIED_WRITE_DISABLED);
|
||||
} else {
|
||||
ClearFlag(SharedCacheMap->Flags, DISABLE_WRITE_BEHIND);
|
||||
}
|
||||
CcReleaseMasterLock( OldIrql );
|
||||
}
|
||||
|
||||
|
||||
NTKERNELAPI
|
||||
BOOLEAN
|
||||
CcSetPrivateWriteFile(
|
||||
PFILE_OBJECT FileObject
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine will instruct the cache manager to treat the file as
|
||||
a private-write stream, so that a caller can implement a private
|
||||
logging mechanism for it. We will turn on both Mm's modify-no-write
|
||||
and our disable-write-behind, and disallow non-aware flush/purge for
|
||||
the file.
|
||||
|
||||
Caching must already be initiated on the file.
|
||||
|
||||
This routine is only exported to the kernel.
|
||||
|
||||
Arguments:
|
||||
|
||||
FileObject - File to make private-write.
|
||||
|
||||
Return Value:
|
||||
|
||||
None.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
PSHARED_CACHE_MAP SharedCacheMap;
|
||||
BOOLEAN Disabled;
|
||||
KIRQL OldIrql;
|
||||
PVACB Vacb;
|
||||
ULONG ActivePage;
|
||||
ULONG PageIsDirty;
|
||||
|
||||
//
|
||||
// Pick up the file exclusive to synchronize against readahead and
|
||||
// other purge/map activity.
|
||||
//
|
||||
|
||||
FsRtlAcquireFileExclusive( FileObject );
|
||||
|
||||
//
|
||||
// Get a pointer to the SharedCacheMap. Be sure to release the FileObject
|
||||
// in case an error condition forces a premature exit.
|
||||
//
|
||||
|
||||
if ((FileObject->SectionObjectPointer == NULL) ||
|
||||
((SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap) == NULL)){
|
||||
FsRtlReleaseFile( FileObject );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Unmap all the views in preparation for making the disable mw call.
|
||||
//
|
||||
|
||||
//
|
||||
// We still need to wait for any dangling cache read or writes.
|
||||
//
|
||||
// In fact we have to loop and wait because the lazy writer can
|
||||
// sneak in and do an CcGetVirtualAddressIfMapped, and we are not
|
||||
// synchronized.
|
||||
//
|
||||
// This is the same bit of code that our purge will do. We assume
|
||||
// that a private writer has succesfully blocked out other activity.
|
||||
//
|
||||
|
||||
//
|
||||
// If there is an active Vacb, then delete it now (before waiting!).
|
||||
//
|
||||
|
||||
CcAcquireMasterLock( &OldIrql );
|
||||
GetActiveVacbAtDpcLevel( SharedCacheMap, Vacb, ActivePage, PageIsDirty );
|
||||
CcReleaseMasterLock( OldIrql );
|
||||
|
||||
if (Vacb != NULL) {
|
||||
|
||||
CcFreeActiveVacb( SharedCacheMap, Vacb, ActivePage, PageIsDirty );
|
||||
}
|
||||
|
||||
while ((SharedCacheMap->Vacbs != NULL) &&
|
||||
!CcUnmapVacbArray( SharedCacheMap, NULL, 0, FALSE )) {
|
||||
|
||||
CcWaitOnActiveCount( SharedCacheMap );
|
||||
}
|
||||
|
||||
//
|
||||
// Knock the file down.
|
||||
//
|
||||
|
||||
CcFlushCache( FileObject->SectionObjectPointer, NULL, 0, NULL );
|
||||
|
||||
//
|
||||
// Now the file is clean and unmapped. We can still have a racing
|
||||
// lazy writer, though.
|
||||
//
|
||||
// We just wait for the lazy writer queue to drain before disabling
|
||||
// modified write. There may be a better way to do this by having
|
||||
// an event for the WRITE_QUEUED flag. ? This would also let us
|
||||
// dispense with the pagingio pick/drop in the FS cache coherency
|
||||
// paths, but there could be reasons why CcFlushCache shouldn't
|
||||
// always do such a block. Investigate this.
|
||||
//
|
||||
// This wait takes on the order of ~.5s avg. case.
|
||||
//
|
||||
|
||||
CcAcquireMasterLock( &OldIrql );
|
||||
|
||||
if (FlagOn( SharedCacheMap->Flags, WRITE_QUEUED ) ||
|
||||
FlagOn( SharedCacheMap->Flags, READ_AHEAD_QUEUED )) {
|
||||
|
||||
CcReleaseMasterLock( OldIrql );
|
||||
FsRtlReleaseFile( FileObject );
|
||||
CcWaitForCurrentLazyWriterActivity();
|
||||
FsRtlAcquireFileExclusive( FileObject );
|
||||
|
||||
} else {
|
||||
|
||||
CcReleaseMasterLock( OldIrql );
|
||||
}
|
||||
|
||||
//
|
||||
// Now set the flags and return. We do not set our MODIFIED_WRITE_DISABLED
|
||||
// since we don't want to fully promote this cache map. Future?
|
||||
//
|
||||
|
||||
Disabled = MmDisableModifiedWriteOfSection( FileObject->SectionObjectPointer );
|
||||
|
||||
if (Disabled) {
|
||||
CcAcquireMasterLock( &OldIrql );
|
||||
SetFlag(SharedCacheMap->Flags, DISABLE_WRITE_BEHIND | PRIVATE_WRITE);
|
||||
CcReleaseMasterLock( OldIrql );
|
||||
}
|
||||
|
||||
//
|
||||
// Now release the file for regular operation.
|
||||
//
|
||||
|
||||
FsRtlReleaseFile( FileObject );
|
||||
|
||||
return Disabled;
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
CcSetLogHandleForFile (
|
||||
__in PFILE_OBJECT FileObject,
|
||||
__in PVOID LogHandle,
|
||||
__in PFLUSH_TO_LSN FlushToLsnRoutine
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine may be called to instruct the Cache Manager to store the
|
||||
specified log handle with the shared cache map for a file, to support
|
||||
subsequent calls to the other routines in this module which effectively
|
||||
perform an associative search for files by log handle.
|
||||
|
||||
Arguments:
|
||||
|
||||
FileObject - File for which the log handle should be stored.
|
||||
|
||||
LogHandle - Log Handle to store.
|
||||
|
||||
FlushToLsnRoutine - A routine to call before flushing buffers for this
|
||||
file, to ensure a log file is flushed to the most
|
||||
recent Lsn for any Bcb being flushed.
|
||||
|
||||
Return Value:
|
||||
|
||||
None.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
PSHARED_CACHE_MAP SharedCacheMap;
|
||||
|
||||
//
|
||||
// Get pointer to SharedCacheMap.
|
||||
//
|
||||
|
||||
SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
|
||||
|
||||
//
|
||||
// Now set the log file handle and flush routine
|
||||
//
|
||||
|
||||
SharedCacheMap->LogHandle = LogHandle;
|
||||
SharedCacheMap->FlushToLsnRoutine = FlushToLsnRoutine;
|
||||
}
|
||||
|
||||
|
||||
LARGE_INTEGER
|
||||
CcGetDirtyPages (
|
||||
__in PVOID LogHandle,
|
||||
__in PDIRTY_PAGE_ROUTINE DirtyPageRoutine,
|
||||
__in PVOID Context1,
|
||||
__in PVOID Context2
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine may be called to return all of the dirty pages in all files
|
||||
for a given log handle. Each page is returned by an individual call to
|
||||
the Dirty Page Routine. The Dirty Page Routine is defined by a prototype
|
||||
in ntos\inc\cache.h.
|
||||
|
||||
Arguments:
|
||||
|
||||
LogHandle - Log Handle which must match the log handle previously stored
|
||||
for all files which are to be returned.
|
||||
|
||||
DirtyPageRoutine -- The routine to call as each dirty page for this log
|
||||
handle is found.
|
||||
|
||||
Context1 - First context parameter to be passed to the Dirty Page Routine.
|
||||
|
||||
Context2 - First context parameter to be passed to the Dirty Page Routine.
|
||||
|
||||
Return Value:
|
||||
|
||||
LARGE_INTEGER - Oldest Lsn found of all the dirty pages, or 0 if no dirty pages
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
PSHARED_CACHE_MAP SharedCacheMap;
|
||||
PBCB Bcb, BcbToUnpin = NULL;
|
||||
KLOCK_QUEUE_HANDLE LockHandle;
|
||||
LARGE_INTEGER SavedFileOffset, SavedOldestLsn, SavedNewestLsn;
|
||||
ULONG SavedByteLength;
|
||||
LARGE_INTEGER OldestLsn = {0,0};
|
||||
|
||||
//
|
||||
// Synchronize with changes to the SharedCacheMap list.
|
||||
//
|
||||
|
||||
CcAcquireMasterLock( &LockHandle.OldIrql );
|
||||
|
||||
SharedCacheMap = CONTAINING_RECORD( CcDirtySharedCacheMapList.SharedCacheMapLinks.Flink,
|
||||
SHARED_CACHE_MAP,
|
||||
SharedCacheMapLinks );
|
||||
|
||||
//
|
||||
// Use try/finally for cleanup. The only spot where we can raise is out of the
|
||||
// filesystem callback, but we have the exception handler out here so we aren't
|
||||
// constantly setting/unsetting it.
|
||||
//
|
||||
|
||||
try {
|
||||
|
||||
while (&SharedCacheMap->SharedCacheMapLinks != &CcDirtySharedCacheMapList.SharedCacheMapLinks) {
|
||||
|
||||
//
|
||||
// Skip over cursors, SharedCacheMaps for other LogHandles, and ones with
|
||||
// no dirty pages
|
||||
//
|
||||
|
||||
if (!FlagOn(SharedCacheMap->Flags, IS_CURSOR) && (SharedCacheMap->LogHandle == LogHandle) &&
|
||||
(SharedCacheMap->DirtyPages != 0)) {
|
||||
|
||||
//
|
||||
// This SharedCacheMap should stick around for a while in the dirty list.
|
||||
//
|
||||
|
||||
CcIncrementOpenCount( SharedCacheMap, 'pdGS' );
|
||||
SharedCacheMap->DirtyPages += 1;
|
||||
CcReleaseMasterLock( LockHandle.OldIrql );
|
||||
|
||||
//
|
||||
// Set our initial resume point and point to first Bcb in List.
|
||||
//
|
||||
|
||||
KeAcquireInStackQueuedSpinLock( &SharedCacheMap->BcbSpinLock, &LockHandle );
|
||||
Bcb = CONTAINING_RECORD( SharedCacheMap->BcbList.Flink, BCB, BcbLinks );
|
||||
|
||||
//
|
||||
// Scan to the end of the Bcb list.
|
||||
//
|
||||
|
||||
while (&Bcb->BcbLinks != &SharedCacheMap->BcbList) {
|
||||
|
||||
//
|
||||
// If the Bcb is dirty, then capture the inputs for the
|
||||
// callback routine so we can call without holding a spinlock.
|
||||
//
|
||||
|
||||
if ((Bcb->NodeTypeCode == CACHE_NTC_BCB) && Bcb->Dirty) {
|
||||
|
||||
SavedFileOffset = Bcb->FileOffset;
|
||||
SavedByteLength = Bcb->ByteLength;
|
||||
SavedOldestLsn = Bcb->OldestLsn;
|
||||
SavedNewestLsn = Bcb->NewestLsn;
|
||||
|
||||
//
|
||||
// Increment PinCount so the Bcb sticks around
|
||||
//
|
||||
|
||||
Bcb->PinCount += 1;
|
||||
|
||||
KeReleaseInStackQueuedSpinLock( &LockHandle );
|
||||
|
||||
//
|
||||
// Any Bcb to unref from a previous loop?
|
||||
//
|
||||
|
||||
if (BcbToUnpin != NULL) {
|
||||
CcUnpinFileData( BcbToUnpin, TRUE, UNREF );
|
||||
BcbToUnpin = NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// Call the file system. This callback may raise status.
|
||||
//
|
||||
|
||||
(*DirtyPageRoutine)( SharedCacheMap->FileObject,
|
||||
&SavedFileOffset,
|
||||
SavedByteLength,
|
||||
&SavedOldestLsn,
|
||||
&SavedNewestLsn,
|
||||
Context1,
|
||||
Context2 );
|
||||
|
||||
//
|
||||
// Possibly update OldestLsn
|
||||
//
|
||||
|
||||
if ((SavedOldestLsn.QuadPart != 0) &&
|
||||
((OldestLsn.QuadPart == 0) || (SavedOldestLsn.QuadPart < OldestLsn.QuadPart ))) {
|
||||
OldestLsn = SavedOldestLsn;
|
||||
}
|
||||
|
||||
//
|
||||
// Now reacquire the spinlock and scan from the resume point
|
||||
// point to the next Bcb to return in the descending list.
|
||||
//
|
||||
|
||||
KeAcquireInStackQueuedSpinLock( &SharedCacheMap->BcbSpinLock, &LockHandle );
|
||||
|
||||
//
|
||||
// Normally the Bcb can stay around a while, but if not,
|
||||
// we will just remember it for the next time we do not
|
||||
// have the spin lock. We cannot unpin it now, because
|
||||
// we would lose our place in the list.
|
||||
//
|
||||
// This is cheating, but it works and is sane since we're
|
||||
// already traversing the bcb list - dropping the bcb count
|
||||
// is OK, as long as we don't hit zero. Zero requires a
|
||||
// slight bit more attention that shouldn't be replicated.
|
||||
// (unmapping the view)
|
||||
//
|
||||
|
||||
if (Bcb->PinCount > 1) {
|
||||
Bcb->PinCount -= 1;
|
||||
} else {
|
||||
BcbToUnpin = Bcb;
|
||||
}
|
||||
}
|
||||
|
||||
Bcb = CONTAINING_RECORD( Bcb->BcbLinks.Flink, BCB, BcbLinks );
|
||||
}
|
||||
KeReleaseInStackQueuedSpinLock( &LockHandle );
|
||||
|
||||
//
|
||||
// We need to unref any Bcb we are holding before moving on to
|
||||
// the next SharedCacheMap, or else CcDeleteSharedCacheMap will
|
||||
// also delete this Bcb.
|
||||
//
|
||||
|
||||
if (BcbToUnpin != NULL) {
|
||||
|
||||
CcUnpinFileData( BcbToUnpin, TRUE, UNREF );
|
||||
BcbToUnpin = NULL;
|
||||
}
|
||||
|
||||
CcAcquireMasterLock( &LockHandle.OldIrql );
|
||||
|
||||
//
|
||||
// Now release the SharedCacheMap, leaving it in the dirty list.
|
||||
//
|
||||
|
||||
CcDecrementOpenCount( SharedCacheMap, 'pdGF' );
|
||||
SharedCacheMap->DirtyPages -= 1;
|
||||
}
|
||||
|
||||
//
|
||||
// Now loop back for the next cache map.
|
||||
//
|
||||
|
||||
SharedCacheMap =
|
||||
CONTAINING_RECORD( SharedCacheMap->SharedCacheMapLinks.Flink,
|
||||
SHARED_CACHE_MAP,
|
||||
SharedCacheMapLinks );
|
||||
}
|
||||
|
||||
CcReleaseMasterLock( LockHandle.OldIrql );
|
||||
|
||||
} finally {
|
||||
|
||||
//
|
||||
// Drop the Bcb if we are being ejected. We are guaranteed that the
|
||||
// only raise is from the callback, at which point we have an incremented
|
||||
// pincount.
|
||||
//
|
||||
|
||||
if (AbnormalTermination()) {
|
||||
|
||||
CcUnpinFileData( Bcb, TRUE, UNPIN );
|
||||
}
|
||||
}
|
||||
|
||||
return OldestLsn;
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN
|
||||
CcIsThereDirtyData (
|
||||
__in PVPB Vpb
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine returns TRUE if the specified Vcb has any unwritten dirty
|
||||
data in the cache.
|
||||
|
||||
Arguments:
|
||||
|
||||
Vpb - specifies Vpb to check for
|
||||
|
||||
Return Value:
|
||||
|
||||
FALSE - if the Vpb has no dirty data
|
||||
TRUE - if the Vpb has dirty data
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
PSHARED_CACHE_MAP SharedCacheMap;
|
||||
KIRQL OldIrql;
|
||||
ULONG LoopsWithLockHeld = 0;
|
||||
|
||||
//
|
||||
// Synchronize with changes to the SharedCacheMap list.
|
||||
//
|
||||
|
||||
CcAcquireMasterLock( &OldIrql );
|
||||
|
||||
SharedCacheMap = CONTAINING_RECORD( CcDirtySharedCacheMapList.SharedCacheMapLinks.Flink,
|
||||
SHARED_CACHE_MAP,
|
||||
SharedCacheMapLinks );
|
||||
|
||||
while (&SharedCacheMap->SharedCacheMapLinks != &CcDirtySharedCacheMapList.SharedCacheMapLinks) {
|
||||
|
||||
//
|
||||
// Look at this one if the Vpb matches and if there is dirty data.
|
||||
// For what it's worth, don't worry about dirty data in temporary files,
|
||||
// as that should not concern the caller if it wants to dismount.
|
||||
//
|
||||
|
||||
if (!FlagOn(SharedCacheMap->Flags, IS_CURSOR) &&
|
||||
(SharedCacheMap->FileObject->Vpb == Vpb) &&
|
||||
(SharedCacheMap->DirtyPages != 0) &&
|
||||
!FlagOn(SharedCacheMap->FileObject->Flags, FO_TEMPORARY_FILE)) {
|
||||
|
||||
CcReleaseMasterLock( OldIrql );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// Make sure we occasionally drop the lock. Set WRITE_QUEUED
|
||||
// to keep the guy from going away, and increment DirtyPages to
|
||||
// keep it in this list.
|
||||
//
|
||||
|
||||
if ((++LoopsWithLockHeld >= 20) &&
|
||||
!FlagOn(SharedCacheMap->Flags, WRITE_QUEUED | IS_CURSOR)) {
|
||||
|
||||
SetFlag( *((ULONG volatile *)&SharedCacheMap->Flags), WRITE_QUEUED);
|
||||
*((ULONG volatile *)&SharedCacheMap->DirtyPages) += 1;
|
||||
CcReleaseMasterLock( OldIrql );
|
||||
LoopsWithLockHeld = 0;
|
||||
CcAcquireMasterLock( &OldIrql );
|
||||
ClearFlag( *((ULONG volatile *)&SharedCacheMap->Flags), WRITE_QUEUED);
|
||||
*((ULONG volatile *)&SharedCacheMap->DirtyPages) -= 1;
|
||||
}
|
||||
|
||||
//
|
||||
// Now loop back for the next cache map.
|
||||
//
|
||||
|
||||
SharedCacheMap =
|
||||
CONTAINING_RECORD( SharedCacheMap->SharedCacheMapLinks.Flink,
|
||||
SHARED_CACHE_MAP,
|
||||
SharedCacheMapLinks );
|
||||
}
|
||||
|
||||
CcReleaseMasterLock( OldIrql );
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LARGE_INTEGER
|
||||
CcGetLsnForFileObject(
|
||||
__in PFILE_OBJECT FileObject,
|
||||
__out_opt PLARGE_INTEGER OldestLsn
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine returns the oldest and newest LSNs for a file object.
|
||||
|
||||
Arguments:
|
||||
|
||||
FileObject - File for which the log handle should be stored.
|
||||
|
||||
OldestLsn - pointer to location to store oldest LSN for file object.
|
||||
|
||||
Return Value:
|
||||
|
||||
The newest LSN for the file object.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
PBCB Bcb;
|
||||
KLOCK_QUEUE_HANDLE LockHandle;
|
||||
LARGE_INTEGER Oldest, Newest;
|
||||
PSHARED_CACHE_MAP SharedCacheMap = FileObject->SectionObjectPointer->SharedCacheMap;
|
||||
|
||||
//
|
||||
// initialize lsn variables
|
||||
//
|
||||
|
||||
Oldest.LowPart = 0;
|
||||
Oldest.HighPart = 0;
|
||||
Newest.LowPart = 0;
|
||||
Newest.HighPart = 0;
|
||||
|
||||
if(SharedCacheMap == NULL) {
|
||||
return Oldest;
|
||||
}
|
||||
|
||||
KeAcquireInStackQueuedSpinLock(&SharedCacheMap->BcbSpinLock, &LockHandle);
|
||||
|
||||
//
|
||||
// Now point to first Bcb in List, and loop through it.
|
||||
//
|
||||
|
||||
Bcb = CONTAINING_RECORD( SharedCacheMap->BcbList.Flink, BCB, BcbLinks );
|
||||
|
||||
while (&Bcb->BcbLinks != &SharedCacheMap->BcbList) {
|
||||
|
||||
//
|
||||
// If the Bcb is dirty then capture the oldest and newest lsn
|
||||
//
|
||||
|
||||
|
||||
if ((Bcb->NodeTypeCode == CACHE_NTC_BCB) && Bcb->Dirty) {
|
||||
|
||||
LARGE_INTEGER BcbLsn, BcbNewest;
|
||||
|
||||
BcbLsn = Bcb->OldestLsn;
|
||||
BcbNewest = Bcb->NewestLsn;
|
||||
|
||||
if ((BcbLsn.QuadPart != 0) &&
|
||||
((Oldest.QuadPart == 0) ||
|
||||
(BcbLsn.QuadPart < Oldest.QuadPart))) {
|
||||
|
||||
Oldest = BcbLsn;
|
||||
}
|
||||
|
||||
if ((BcbLsn.QuadPart != 0) && (BcbNewest.QuadPart > Newest.QuadPart)) {
|
||||
|
||||
Newest = BcbNewest;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Bcb = CONTAINING_RECORD( Bcb->BcbLinks.Flink, BCB, BcbLinks );
|
||||
}
|
||||
|
||||
//
|
||||
// Now release the spin lock for this Bcb list and generate a callback
|
||||
// if we got something.
|
||||
//
|
||||
|
||||
KeReleaseInStackQueuedSpinLock( &LockHandle );
|
||||
|
||||
if (ARGUMENT_PRESENT(OldestLsn)) {
|
||||
|
||||
*OldestLsn = Oldest;
|
||||
}
|
||||
|
||||
return Newest;
|
||||
}
|
||||
1161
base/ntos/cache/mdlsup.c
vendored
Normal file
1161
base/ntos/cache/mdlsup.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1565
base/ntos/cache/pinsup.c
vendored
Normal file
1565
base/ntos/cache/pinsup.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3425
base/ntos/cache/vacbsup.c
vendored
Normal file
3425
base/ntos/cache/vacbsup.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
69
base/ntos/config/BUILD/makefile
Normal file
69
base/ntos/config/BUILD/makefile
Normal file
@ -0,0 +1,69 @@
|
||||
#
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
#
|
||||
# You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
# If you do not agree to the terms, do not use the code.
|
||||
#
|
||||
|
||||
library = $(module)
|
||||
specialcflags = -D_WANT_MACHINE_IDENTIFICATION
|
||||
|
||||
asobjs=
|
||||
ccarchobjs=
|
||||
|
||||
ccobjs= \
|
||||
$(OBJ)\cmapi.obj \
|
||||
$(OBJ)\cmapi2.obj \
|
||||
$(OBJ)\cmboot.obj \
|
||||
$(OBJ)\cmchek.obj \
|
||||
$(OBJ)\cmchek2.obj \
|
||||
$(OBJ)\cmclose.obj \
|
||||
$(OBJ)\cmconfig.obj \
|
||||
$(OBJ)\cmcontrl.obj \
|
||||
$(OBJ)\cmdat.obj \
|
||||
$(OBJ)\cmdat2.obj \
|
||||
$(OBJ)\cmdatini.obj \
|
||||
$(OBJ)\cmdelete.obj \
|
||||
$(OBJ)\cmgquota.obj \
|
||||
$(OBJ)\cmhvlist.obj \
|
||||
$(OBJ)\cmindex.obj \
|
||||
$(OBJ)\cminit.obj \
|
||||
$(OBJ)\cmname.obj \
|
||||
$(OBJ)\cmnotify.obj \
|
||||
$(OBJ)\cmparse.obj \
|
||||
$(OBJ)\cmparse2.obj \
|
||||
$(OBJ)\cmquery.obj \
|
||||
$(OBJ)\cmsavres.obj \
|
||||
$(OBJ)\cmsubs.obj \
|
||||
$(OBJ)\cmsubs2.obj \
|
||||
$(OBJ)\cmsubs3.obj \
|
||||
$(OBJ)\cmse.obj \
|
||||
$(OBJ)\cmsysini.obj \
|
||||
$(OBJ)\cmtrecpy.obj \
|
||||
$(OBJ)\cmtredel.obj \
|
||||
$(OBJ)\cmtree.obj \
|
||||
$(OBJ)\cmworker.obj \
|
||||
$(OBJ)\cmwrapr.obj \
|
||||
$(OBJ)\cmwrapr2.obj \
|
||||
$(OBJ)\cmwmi.obj \
|
||||
$(OBJ)\cmmapvw.obj \
|
||||
$(OBJ)\cmdelay.obj \
|
||||
$(OBJ)\cmvalue.obj \
|
||||
$(OBJ)\cmsecache.obj \
|
||||
$(OBJ)\cmdown.obj \
|
||||
$(OBJ)\cmalloc.obj \
|
||||
$(OBJ)\cmhook.obj \
|
||||
$(OBJ)\hivebin.obj \
|
||||
$(OBJ)\hivecell.obj \
|
||||
$(OBJ)\hivechek.obj \
|
||||
$(OBJ)\hivefree.obj \
|
||||
$(OBJ)\hiveinit.obj \
|
||||
$(OBJ)\hiveload.obj \
|
||||
$(OBJ)\hivemap.obj \
|
||||
$(OBJ)\hivesum.obj \
|
||||
$(OBJ)\hivesync.obj \
|
||||
$(OBJ)\hivehint.obj \
|
||||
$(OBJ)\ntapi.obj
|
||||
|
||||
!include $(ntos)\BUILD\makefile.build
|
||||
|
||||
554
base/ntos/config/cmalloc.c
Normal file
554
base/ntos/config/cmalloc.c
Normal file
@ -0,0 +1,554 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
cmalloc.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Provides routines for implementing the registry's own pool allocator.
|
||||
|
||||
--*/
|
||||
|
||||
#include "cmp.h"
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(INIT,CmpInitCmPrivateAlloc)
|
||||
#pragma alloc_text(PAGE,CmpDestroyCmPrivateAlloc)
|
||||
#pragma alloc_text(PAGE,CmpAllocateKeyControlBlock)
|
||||
#pragma alloc_text(PAGE,CmpFreeKeyControlBlock)
|
||||
#pragma alloc_text(INIT,CmpInitCmPrivateDelayAlloc)
|
||||
#pragma alloc_text(PAGE,CmpDestroyCmPrivateDelayAlloc)
|
||||
#pragma alloc_text(PAGE,CmpAllocateDelayItem)
|
||||
#pragma alloc_text(PAGE,CmpFreeDelayItem)
|
||||
#endif
|
||||
|
||||
typedef struct _CM_ALLOC_PAGE {
|
||||
ULONG FreeCount; // number of free kcbs
|
||||
ULONG Reserved; // alignment
|
||||
PVOID AllocPage; // crud allocations - this member is NOT USED
|
||||
} CM_ALLOC_PAGE, *PCM_ALLOC_PAGE;
|
||||
|
||||
#define CM_KCB_ENTRY_SIZE sizeof( CM_KEY_CONTROL_BLOCK )
|
||||
#define CM_KCBS_PER_PAGE ((PAGE_SIZE - FIELD_OFFSET(CM_ALLOC_PAGE,AllocPage)) / CM_KCB_ENTRY_SIZE)
|
||||
|
||||
#define KCB_TO_PAGE_ADDRESS( kcb ) (PVOID)(((ULONG_PTR)(kcb)) & ~(PAGE_SIZE - 1))
|
||||
#define KCB_TO_ALLOC_PAGE( kcb ) ((PCM_ALLOC_PAGE)KCB_TO_PAGE_ADDRESS(kcb))
|
||||
|
||||
LIST_ENTRY CmpFreeKCBListHead; // list of free kcbs
|
||||
BOOLEAN CmpAllocInited = FALSE;
|
||||
|
||||
KGUARDED_MUTEX CmpAllocBucketLock; // used to protect the bucket
|
||||
|
||||
#define LOCK_ALLOC_BUCKET() KeAcquireGuardedMutex(&CmpAllocBucketLock)
|
||||
#define UNLOCK_ALLOC_BUCKET() KeReleaseGuardedMutex(&CmpAllocBucketLock)
|
||||
|
||||
VOID
|
||||
CmpInitCmPrivateAlloc( )
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Initialize the CmPrivate pool allocation module
|
||||
|
||||
Arguments:
|
||||
|
||||
|
||||
Return Value:
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
if( CmpAllocInited ) {
|
||||
//
|
||||
// already initialized
|
||||
//
|
||||
return;
|
||||
}
|
||||
|
||||
InitializeListHead(&(CmpFreeKCBListHead));
|
||||
|
||||
//
|
||||
// init the bucket lock
|
||||
//
|
||||
KeInitializeGuardedMutex(&CmpAllocBucketLock);
|
||||
|
||||
CmpAllocInited = TRUE;
|
||||
}
|
||||
|
||||
VOID
|
||||
CmpDestroyCmPrivateAlloc( )
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Frees memory used byt the CmPrivate pool allocation module
|
||||
|
||||
Arguments:
|
||||
|
||||
|
||||
Return Value:
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
PAGED_CODE();
|
||||
|
||||
if( !CmpAllocInited ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PCM_KEY_CONTROL_BLOCK
|
||||
CmpAllocateKeyControlBlock( )
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Allocates a kcb; first try from our own allocator.
|
||||
If it doesn't work (we have maxed out our number of allocs
|
||||
or private allocator is not initialized)
|
||||
try from paged pool
|
||||
|
||||
Arguments:
|
||||
|
||||
|
||||
Return Value:
|
||||
|
||||
The new kcb
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
USHORT j;
|
||||
PCM_KEY_CONTROL_BLOCK kcb = NULL;
|
||||
PCM_ALLOC_PAGE AllocPage;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
if( !CmpAllocInited ) {
|
||||
//
|
||||
// not initialized
|
||||
//
|
||||
goto AllocFromPool;
|
||||
}
|
||||
|
||||
LOCK_ALLOC_BUCKET();
|
||||
|
||||
SearchFreeKcb:
|
||||
//
|
||||
// try to find a free one
|
||||
//
|
||||
if( IsListEmpty(&CmpFreeKCBListHead) == FALSE ) {
|
||||
//
|
||||
// found one
|
||||
//
|
||||
kcb = (PCM_KEY_CONTROL_BLOCK)RemoveHeadList(&CmpFreeKCBListHead);
|
||||
kcb = CONTAINING_RECORD(kcb,
|
||||
CM_KEY_CONTROL_BLOCK,
|
||||
FreeListEntry);
|
||||
|
||||
AllocPage = (PCM_ALLOC_PAGE)KCB_TO_ALLOC_PAGE( kcb );
|
||||
|
||||
ASSERT( AllocPage->FreeCount != 0 );
|
||||
|
||||
AllocPage->FreeCount--;
|
||||
|
||||
//
|
||||
// set when page was allocated
|
||||
//
|
||||
ASSERT( kcb->PrivateAlloc == 1);
|
||||
|
||||
UNLOCK_ALLOC_BUCKET();
|
||||
return kcb;
|
||||
}
|
||||
|
||||
//
|
||||
// we need to allocate a new page as we ran out of free kcbs
|
||||
//
|
||||
|
||||
//
|
||||
// allocate a new page and insert all kcbs in the freelist
|
||||
//
|
||||
AllocPage = (PCM_ALLOC_PAGE)ExAllocatePoolWithTag(PagedPool, PAGE_SIZE, CM_ALLOCATE_TAG|PROTECTED_POOL);
|
||||
if( AllocPage == NULL ) {
|
||||
//
|
||||
// we might be low on pool; maybe small pool chunks will work
|
||||
//
|
||||
UNLOCK_ALLOC_BUCKET();
|
||||
goto AllocFromPool;
|
||||
}
|
||||
|
||||
//
|
||||
// set up the page
|
||||
//
|
||||
AllocPage->FreeCount = CM_KCBS_PER_PAGE;
|
||||
|
||||
//
|
||||
// now the dirty job; insert all kcbs inside the page in the free list
|
||||
//
|
||||
for(j=0;j<CM_KCBS_PER_PAGE;j++) {
|
||||
kcb = (PCM_KEY_CONTROL_BLOCK)((PUCHAR)AllocPage + FIELD_OFFSET(CM_ALLOC_PAGE,AllocPage) + j*CM_KCB_ENTRY_SIZE);
|
||||
|
||||
//
|
||||
// set it here; only once
|
||||
//
|
||||
kcb->PrivateAlloc = 1;
|
||||
kcb->DelayCloseEntry = NULL;
|
||||
|
||||
InsertTailList(
|
||||
&CmpFreeKCBListHead,
|
||||
&(kcb->FreeListEntry)
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// this time will find one for sure
|
||||
//
|
||||
goto SearchFreeKcb;
|
||||
|
||||
AllocFromPool:
|
||||
kcb = ExAllocatePoolWithTag(PagedPool,
|
||||
sizeof(CM_KEY_CONTROL_BLOCK),
|
||||
CM_KCB_TAG | PROTECTED_POOL);
|
||||
|
||||
if( kcb != NULL ) {
|
||||
//
|
||||
// clear the private alloc flag
|
||||
//
|
||||
kcb->PrivateAlloc = 0;
|
||||
kcb->DelayCloseEntry = NULL;
|
||||
}
|
||||
|
||||
return kcb;
|
||||
}
|
||||
|
||||
#define LogKCBFree(kcb) //nothing
|
||||
|
||||
VOID
|
||||
CmpFreeKeyControlBlock( PCM_KEY_CONTROL_BLOCK kcb )
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Frees a kcb; if it's allocated from our own pool put it back in the free list.
|
||||
If it's allocated from general pool, just free it.
|
||||
|
||||
Arguments:
|
||||
|
||||
kcb to free
|
||||
|
||||
Return Value:
|
||||
|
||||
|
||||
--*/
|
||||
{
|
||||
USHORT j;
|
||||
PCM_ALLOC_PAGE AllocPage;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
ASSERT_KEYBODY_LIST_EMPTY(kcb);
|
||||
|
||||
#if defined(_WIN64)
|
||||
//
|
||||
// free cached name if any
|
||||
//
|
||||
if( (kcb->RealKeyName != NULL) && (kcb->RealKeyName != CMP_KCB_REAL_NAME_UPCASE) ) {
|
||||
ExFreePoolWithTag(kcb->RealKeyName, CM_NAME_TAG);
|
||||
}
|
||||
#endif
|
||||
|
||||
if( !kcb->PrivateAlloc ) {
|
||||
//
|
||||
// just free it and be done with it
|
||||
//
|
||||
ExFreePoolWithTag(kcb, CM_KCB_TAG | PROTECTED_POOL);
|
||||
return;
|
||||
}
|
||||
|
||||
LOCK_ALLOC_BUCKET();
|
||||
|
||||
ASSERT_HASH_ENTRY_LOCKED_EXCLUSIVE(kcb->ConvKey);
|
||||
LogKCBFree(kcb);
|
||||
|
||||
//
|
||||
// add kcb to freelist
|
||||
//
|
||||
InsertTailList(
|
||||
&CmpFreeKCBListHead,
|
||||
&(kcb->FreeListEntry)
|
||||
);
|
||||
|
||||
//
|
||||
// get the page
|
||||
//
|
||||
AllocPage = (PCM_ALLOC_PAGE)KCB_TO_ALLOC_PAGE( kcb );
|
||||
|
||||
//
|
||||
// not all are free
|
||||
//
|
||||
ASSERT( AllocPage->FreeCount != CM_KCBS_PER_PAGE);
|
||||
|
||||
AllocPage->FreeCount++;
|
||||
|
||||
if( AllocPage->FreeCount == CM_KCBS_PER_PAGE ) {
|
||||
//
|
||||
// entire page is free; let it go
|
||||
//
|
||||
//
|
||||
// first; iterate through the free kcb list and remove all kcbs inside this page
|
||||
//
|
||||
for(j=0;j<CM_KCBS_PER_PAGE;j++) {
|
||||
kcb = (PCM_KEY_CONTROL_BLOCK)((PUCHAR)AllocPage + FIELD_OFFSET(CM_ALLOC_PAGE,AllocPage) + j*CM_KCB_ENTRY_SIZE);
|
||||
|
||||
RemoveEntryList(&(kcb->FreeListEntry));
|
||||
}
|
||||
ExFreePoolWithTag(AllocPage, CM_ALLOCATE_TAG|PROTECTED_POOL);
|
||||
}
|
||||
|
||||
UNLOCK_ALLOC_BUCKET();
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// delay deref and delay close private allocator
|
||||
//
|
||||
|
||||
LIST_ENTRY CmpFreeDelayItemsListHead; // list of free delay items
|
||||
|
||||
KGUARDED_MUTEX CmpDelayAllocBucketLock; // used to protect the bucket
|
||||
|
||||
#define LOCK_DELAY_ALLOC_BUCKET() KeAcquireGuardedMutex(&CmpDelayAllocBucketLock)
|
||||
#define UNLOCK_DELAY_ALLOC_BUCKET() KeReleaseGuardedMutex(&CmpDelayAllocBucketLock)
|
||||
|
||||
|
||||
|
||||
#define CM_DELAY_ALLOC_ENTRY_SIZE sizeof( CM_DELAY_ALLOC )
|
||||
#define CM_DELAYS_PER_PAGE ((PAGE_SIZE - FIELD_OFFSET(CM_ALLOC_PAGE,AllocPage)) / CM_DELAY_ALLOC_ENTRY_SIZE)
|
||||
|
||||
#define DELAY_ALLOC_TO_PAGE_ADDRESS( delay ) (PVOID)(((ULONG_PTR)(delay)) & ~(PAGE_SIZE - 1))
|
||||
#define DELAY_ALLOC_TO_ALLOC_PAGE( delay ) ((PCM_ALLOC_PAGE)DELAY_ALLOC_TO_PAGE_ADDRESS(delay))
|
||||
|
||||
|
||||
VOID
|
||||
CmpInitCmPrivateDelayAlloc( )
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Initialize the CmPrivate pool allocation module for delay related allocs
|
||||
|
||||
Arguments:
|
||||
|
||||
|
||||
Return Value:
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
InitializeListHead(&(CmpFreeDelayItemsListHead));
|
||||
|
||||
//
|
||||
// init the bucket lock
|
||||
//
|
||||
KeInitializeGuardedMutex(&CmpDelayAllocBucketLock);
|
||||
}
|
||||
|
||||
VOID
|
||||
CmpDestroyCmPrivateDelayAlloc( )
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Frees memory used by the CmPrivate pool allocation module
|
||||
|
||||
Arguments:
|
||||
|
||||
|
||||
Return Value:
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
CM_PAGED_CODE();
|
||||
}
|
||||
|
||||
|
||||
PVOID
|
||||
CmpAllocateDelayItem( )
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Allocates a delay item from our own pool;
|
||||
|
||||
Arguments:
|
||||
|
||||
|
||||
Return Value:
|
||||
|
||||
The new item
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
USHORT j;
|
||||
PCM_DELAY_ALLOC DelayItem = NULL;
|
||||
PCM_ALLOC_PAGE AllocPage;
|
||||
|
||||
CM_PAGED_CODE();
|
||||
|
||||
|
||||
LOCK_DELAY_ALLOC_BUCKET();
|
||||
|
||||
SearchFreeItem:
|
||||
//
|
||||
// try to find a free one
|
||||
//
|
||||
if( CmpIsListEmpty(&CmpFreeDelayItemsListHead) == FALSE ) {
|
||||
//
|
||||
// found one
|
||||
//
|
||||
DelayItem = (PCM_DELAY_ALLOC)RemoveHeadList(&CmpFreeDelayItemsListHead);
|
||||
DelayItem = CONTAINING_RECORD( DelayItem,
|
||||
CM_DELAY_ALLOC,
|
||||
ListEntry);
|
||||
|
||||
CmpClearListEntry(&(DelayItem->ListEntry));
|
||||
|
||||
AllocPage = (PCM_ALLOC_PAGE)DELAY_ALLOC_TO_ALLOC_PAGE( DelayItem );
|
||||
|
||||
ASSERT( AllocPage->FreeCount != 0 );
|
||||
|
||||
AllocPage->FreeCount--;
|
||||
|
||||
UNLOCK_DELAY_ALLOC_BUCKET();
|
||||
return DelayItem;
|
||||
}
|
||||
|
||||
//
|
||||
// we need to allocate a new page as we ran out of free items
|
||||
//
|
||||
|
||||
//
|
||||
// allocate a new page and insert all kcbs in the freelist
|
||||
//
|
||||
AllocPage = (PCM_ALLOC_PAGE)ExAllocatePoolWithTag(PagedPool, PAGE_SIZE, CM_ALLOCATE_TAG|PROTECTED_POOL);
|
||||
if( AllocPage == NULL ) {
|
||||
//
|
||||
// bad luck
|
||||
//
|
||||
UNLOCK_DELAY_ALLOC_BUCKET();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// set up the page
|
||||
//
|
||||
AllocPage->FreeCount = CM_DELAYS_PER_PAGE;
|
||||
|
||||
//
|
||||
// now the dirty job; insert all items inside the page in the free list
|
||||
//
|
||||
for(j=0;j<CM_DELAYS_PER_PAGE;j++) {
|
||||
DelayItem = (PCM_DELAY_ALLOC)((PUCHAR)AllocPage + FIELD_OFFSET(CM_ALLOC_PAGE,AllocPage) + j*CM_DELAY_ALLOC_ENTRY_SIZE);
|
||||
|
||||
InsertTailList(
|
||||
&CmpFreeDelayItemsListHead,
|
||||
&(DelayItem->ListEntry)
|
||||
);
|
||||
DelayItem->Kcb = NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// this time will find one for sure
|
||||
//
|
||||
goto SearchFreeItem;
|
||||
}
|
||||
|
||||
extern LIST_ENTRY CmpDelayDerefKCBListHead;
|
||||
extern LIST_ENTRY CmpDelayedLRUListHead;
|
||||
|
||||
VOID
|
||||
CmpFreeDelayItem( PVOID Item )
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Frees a kcb; if it's allocated from our own pool put it back in the free list.
|
||||
If it's allocated from general pool, just free it.
|
||||
|
||||
Arguments:
|
||||
|
||||
kcb to free
|
||||
|
||||
Return Value:
|
||||
|
||||
|
||||
--*/
|
||||
{
|
||||
USHORT j;
|
||||
PCM_ALLOC_PAGE AllocPage;
|
||||
PCM_DELAY_ALLOC DelayItem = (PCM_DELAY_ALLOC)Item;
|
||||
|
||||
CM_PAGED_CODE();
|
||||
|
||||
LOCK_DELAY_ALLOC_BUCKET();
|
||||
|
||||
//
|
||||
// add kcb to freelist
|
||||
//
|
||||
InsertTailList(
|
||||
&CmpFreeDelayItemsListHead,
|
||||
&(DelayItem->ListEntry)
|
||||
);
|
||||
|
||||
//
|
||||
// get the page
|
||||
//
|
||||
AllocPage = (PCM_ALLOC_PAGE)DELAY_ALLOC_TO_ALLOC_PAGE( DelayItem );
|
||||
|
||||
//
|
||||
// not all are free
|
||||
//
|
||||
ASSERT( AllocPage->FreeCount != CM_DELAYS_PER_PAGE);
|
||||
|
||||
AllocPage->FreeCount++;
|
||||
|
||||
if( AllocPage->FreeCount == CM_DELAYS_PER_PAGE ) {
|
||||
//
|
||||
// entire page is free; let it go
|
||||
//
|
||||
//
|
||||
// first; iterate through the free item list and remove all items inside this page
|
||||
//
|
||||
for(j=0;j<CM_DELAYS_PER_PAGE;j++) {
|
||||
DelayItem = (PCM_DELAY_ALLOC)((PUCHAR)AllocPage + FIELD_OFFSET(CM_ALLOC_PAGE,AllocPage) + j*CM_DELAY_ALLOC_ENTRY_SIZE);
|
||||
CmpRemoveEntryList(&(DelayItem->ListEntry));
|
||||
}
|
||||
ExFreePoolWithTag(AllocPage, CM_ALLOCATE_TAG|PROTECTED_POOL);
|
||||
}
|
||||
|
||||
UNLOCK_DELAY_ALLOC_BUCKET();
|
||||
}
|
||||
|
||||
4856
base/ntos/config/cmapi.c
Normal file
4856
base/ntos/config/cmapi.c
Normal file
File diff suppressed because it is too large
Load Diff
195
base/ntos/config/cmapi2.c
Normal file
195
base/ntos/config/cmapi2.c
Normal file
@ -0,0 +1,195 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
cmapi2.c
|
||||
|
||||
Abstract:
|
||||
|
||||
This module contains CM level entry points for the registry,
|
||||
particularly those which we don't want to link into tools,
|
||||
setup, the boot loader, etc.
|
||||
|
||||
--*/
|
||||
|
||||
#include "cmp.h"
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE,CmDeleteKey)
|
||||
#endif
|
||||
|
||||
|
||||
NTSTATUS
|
||||
CmDeleteKey(
|
||||
IN PCM_KEY_BODY KeyBody
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Delete a registry key, clean up Notify block.
|
||||
|
||||
Arguments:
|
||||
|
||||
KeyBody - pointer to key handle object
|
||||
|
||||
Return Value:
|
||||
|
||||
NTSTATUS
|
||||
|
||||
--*/
|
||||
{
|
||||
NTSTATUS status;
|
||||
PCM_KEY_NODE ptarget;
|
||||
PHHIVE Hive;
|
||||
HCELL_INDEX Cell;
|
||||
HCELL_INDEX Parent;
|
||||
PCM_KEY_CONTROL_BLOCK KeyControlBlock;
|
||||
LARGE_INTEGER TimeStamp;
|
||||
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_CM,"CmDeleteKey\n"));
|
||||
|
||||
CmpLockRegistry();
|
||||
|
||||
//
|
||||
// If already marked for deletion, storage is gone, so
|
||||
// do nothing and return success.
|
||||
//
|
||||
KeyControlBlock = KeyBody->KeyControlBlock;
|
||||
|
||||
if( KeyControlBlock->ParentKcb == NULL ) {
|
||||
//
|
||||
// cannot delete \Registry
|
||||
//
|
||||
CmpUnlockRegistry();
|
||||
return STATUS_CANNOT_DELETE;
|
||||
}
|
||||
|
||||
PERFINFO_REG_DELETE_KEY(KeyControlBlock);
|
||||
//
|
||||
// serialize access to this key. and its parent
|
||||
// need to lock them both atomically
|
||||
//
|
||||
CmpLockTwoHashEntriesExclusive(KeyControlBlock->ConvKey,KeyControlBlock->ParentKcb->ConvKey);
|
||||
|
||||
if (KeyControlBlock->Delete == TRUE) {
|
||||
status = STATUS_SUCCESS;
|
||||
goto Exit;
|
||||
}
|
||||
Hive = KeyControlBlock->KeyHive;
|
||||
Cell = KeyControlBlock->KeyCell;
|
||||
//
|
||||
// no flush from this point on
|
||||
//
|
||||
CmpLockHiveFlusherShared((PCMHIVE)KeyControlBlock->KeyHive);
|
||||
|
||||
// Mark the hive as read only
|
||||
CmpMarkAllBinsReadOnly(KeyControlBlock->KeyHive);
|
||||
|
||||
ptarget = (PCM_KEY_NODE)HvGetCell(KeyControlBlock->KeyHive, KeyControlBlock->KeyCell);
|
||||
if( ptarget == NULL ) {
|
||||
//
|
||||
// we couldn't map a view for the bin containing this cell
|
||||
//
|
||||
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto Exit2;
|
||||
}
|
||||
|
||||
ASSERT( ptarget->Flags == KeyControlBlock->Flags );
|
||||
|
||||
if ( ((ptarget->SubKeyCounts[Stable] + ptarget->SubKeyCounts[Volatile]) == 0) &&
|
||||
((ptarget->Flags & KEY_NO_DELETE) == 0))
|
||||
{
|
||||
//
|
||||
// Cell is NOT marked NO_DELETE and does NOT have children
|
||||
// Send Notification while key still present, if delete fails,
|
||||
// we'll have sent a spurious notify, that doesn't matter
|
||||
// Delete the actual storage
|
||||
//
|
||||
Parent = ptarget->Parent;
|
||||
|
||||
CmpReportNotify(
|
||||
KeyControlBlock,
|
||||
Hive,
|
||||
Cell,
|
||||
REG_NOTIFY_CHANGE_NAME
|
||||
);
|
||||
|
||||
status = CmpFreeKeyByCell(Hive, Cell, TRUE);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
//
|
||||
// post any waiting notifies
|
||||
//
|
||||
CmpFlushNotifiesOnKeyBodyList(KeyControlBlock,FALSE);
|
||||
|
||||
//
|
||||
// Remove kcb out of cache, but do NOT
|
||||
// free its storage, CmDelete will do that when
|
||||
// the RefCount becomes zero.
|
||||
//
|
||||
// There are two things that can hold the RefCount non-zero.
|
||||
//
|
||||
// 1. open handles for this key
|
||||
// 2. Fake subKeys that are still in DelayClose.
|
||||
//
|
||||
// At this point, we have no way of deleting the fake subkeys from cache
|
||||
// unless we do a search for the whole cache, which is too expensive.
|
||||
// Thus, we decide to either let the fake keys age out of cache or when
|
||||
// someone is doing the lookup for the fake key, then we delete it at that point.
|
||||
// See routine CmpCacheLookup in cmparse.c for more details.
|
||||
//
|
||||
// If the parent has the subkey info or hint cached, free it.
|
||||
// Again, registry is locked exclusively, no need to lock KCB.
|
||||
//
|
||||
CmpCleanUpSubKeyInfo(KeyControlBlock->ParentKcb);
|
||||
ptarget = (PCM_KEY_NODE)HvGetCell(Hive, Parent);
|
||||
if( ptarget != NULL ) {
|
||||
|
||||
//
|
||||
// this should always be true as CmpFreeKeyByCell always marks the parent dirty on success
|
||||
//
|
||||
KeyControlBlock->ParentKcb->KcbMaxNameLen = (USHORT)ptarget->MaxNameLen;
|
||||
// sanity
|
||||
ASSERT_CELL_DIRTY(Hive,Parent);
|
||||
//
|
||||
// update the LastWriteTime on parent and kcb too
|
||||
//
|
||||
KeQuerySystemTime(&TimeStamp);
|
||||
ptarget->LastWriteTime = TimeStamp;
|
||||
KeyBody->KeyControlBlock->ParentKcb->KcbLastWriteTime = TimeStamp;
|
||||
HvReleaseCell(Hive, Parent);
|
||||
}
|
||||
|
||||
KeyControlBlock->Delete = TRUE;
|
||||
CmpRemoveKeyControlBlock(KeyControlBlock);
|
||||
KeyControlBlock->KeyCell = HCELL_NIL;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
status = STATUS_CANNOT_DELETE;
|
||||
|
||||
}
|
||||
|
||||
Exit2:
|
||||
HvReleaseCell(Hive, Cell);
|
||||
CmpUnlockHiveFlusher((PCMHIVE)KeyControlBlock->KeyHive);
|
||||
|
||||
Exit:
|
||||
CmpUnlockTwoHashEntries(KeyControlBlock->ConvKey,KeyControlBlock->ParentKcb->ConvKey);
|
||||
|
||||
CmpUnlockRegistry();
|
||||
|
||||
// Mark the hive as read only
|
||||
CmpMarkAllBinsReadOnly(KeyControlBlock->KeyHive);
|
||||
|
||||
return status;
|
||||
}
|
||||
2781
base/ntos/config/cmboot.c
Normal file
2781
base/ntos/config/cmboot.c
Normal file
File diff suppressed because it is too large
Load Diff
1284
base/ntos/config/cmchek.c
Normal file
1284
base/ntos/config/cmchek.c
Normal file
File diff suppressed because it is too large
Load Diff
189
base/ntos/config/cmchek2.c
Normal file
189
base/ntos/config/cmchek2.c
Normal file
@ -0,0 +1,189 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
cmchek2.c
|
||||
|
||||
Abstract:
|
||||
|
||||
This module implements consistency checking for the registry.
|
||||
|
||||
--*/
|
||||
|
||||
#include "cmp.h"
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE,CmpValidateHiveSecurityDescriptors)
|
||||
#endif
|
||||
|
||||
extern ULONG CmpUsedStorage;
|
||||
|
||||
BOOLEAN
|
||||
CmpValidateHiveSecurityDescriptors(
|
||||
IN PHHIVE Hive,
|
||||
OUT PBOOLEAN ResetSD
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Walks the list of security descriptors present in the hive and passes
|
||||
each security descriptor to RtlValidSecurityDescriptor.
|
||||
|
||||
Only applies to descriptors in Stable store. Those in Volatile store
|
||||
cannot have come from disk and therefore do not need this treatment
|
||||
anyway.
|
||||
|
||||
Arguments:
|
||||
|
||||
Hive - Supplies pointer to the hive control structure
|
||||
|
||||
Return Value:
|
||||
|
||||
TRUE - All security descriptors are valid
|
||||
FALSE - At least one security descriptor is invalid
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
PCM_KEY_NODE RootNode;
|
||||
PCM_KEY_SECURITY SecurityCell;
|
||||
HCELL_INDEX ListAnchor;
|
||||
HCELL_INDEX NextCell;
|
||||
HCELL_INDEX LastCell;
|
||||
BOOLEAN BuildSecurityCache;
|
||||
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SEC,"CmpValidateHiveSecurityDescriptor: Hive = %p\n",(ULONG_PTR)Hive));
|
||||
|
||||
ASSERT( Hive->ReleaseCellRoutine == NULL );
|
||||
|
||||
*ResetSD = FALSE;
|
||||
|
||||
if( ((PCMHIVE)Hive)->SecurityCount == 0 ) {
|
||||
BuildSecurityCache = TRUE;
|
||||
} else {
|
||||
BuildSecurityCache = FALSE;
|
||||
}
|
||||
if (!HvIsCellAllocated(Hive,Hive->BaseBlock->RootCell)) {
|
||||
//
|
||||
// root cell HCELL_INDEX is bogus
|
||||
//
|
||||
return(FALSE);
|
||||
}
|
||||
RootNode = (PCM_KEY_NODE) HvGetCell(Hive, Hive->BaseBlock->RootCell);
|
||||
if( RootNode == NULL ) {
|
||||
//
|
||||
// we couldn't map a view for the bin containing this cell
|
||||
//
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if( FALSE ) {
|
||||
YankSD:
|
||||
if( CmDoSelfHeal() ) {
|
||||
//
|
||||
// reset all security for the entire hive to the root security. There is no reliable way to
|
||||
// patch the security list
|
||||
//
|
||||
if(!HvIsCellAllocated(Hive, RootNode->Security)) {
|
||||
return FALSE;
|
||||
}
|
||||
SecurityCell = (PCM_KEY_SECURITY) HvGetCell(Hive, RootNode->Security);
|
||||
if( SecurityCell == NULL ) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if( HvMarkCellDirty(Hive, RootNode->Security,FALSE) ) {
|
||||
SecurityCell->Flink = SecurityCell->Blink = RootNode->Security;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
//
|
||||
// destroy existing cache and set up an empty one
|
||||
//
|
||||
CmpDestroySecurityCache((PCMHIVE)Hive);
|
||||
CmpInitSecurityCache((PCMHIVE)Hive);
|
||||
CmMarkSelfHeal(Hive);
|
||||
*ResetSD = TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
LastCell = 0;
|
||||
ListAnchor = NextCell = RootNode->Security;
|
||||
|
||||
do {
|
||||
if (!HvIsCellAllocated(Hive, NextCell)) {
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SEC,"CM: CmpValidateHiveSecurityDescriptors\n"));
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SEC," NextCell: %08lx is invalid HCELL_INDEX\n",NextCell));
|
||||
goto YankSD;
|
||||
}
|
||||
SecurityCell = (PCM_KEY_SECURITY) HvGetCell(Hive, NextCell);
|
||||
if( SecurityCell == NULL ) {
|
||||
//
|
||||
// we couldn't map a view for the bin containing this cell
|
||||
//
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (NextCell != ListAnchor) {
|
||||
//
|
||||
// Check to make sure that our Blink points to where we just
|
||||
// came from.
|
||||
//
|
||||
if (SecurityCell->Blink != LastCell) {
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SEC," Invalid Blink (%08lx) on security cell %08lx\n",SecurityCell->Blink, NextCell));
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SEC," should point to %08lx\n", LastCell));
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SEC,"CmpValidSD: SD shared by %d nodes\n",SecurityCell->ReferenceCount));
|
||||
if (!SeValidSecurityDescriptor(SecurityCell->DescriptorLength, &SecurityCell->Descriptor)) {
|
||||
#if DBG
|
||||
CmpDumpSecurityDescriptor(&SecurityCell->Descriptor,"INVALID DESCRIPTOR");
|
||||
#endif
|
||||
goto YankSD;
|
||||
}
|
||||
//
|
||||
// cache this security cell; now that we know it is valid
|
||||
//
|
||||
if( BuildSecurityCache == TRUE ) {
|
||||
if( !NT_SUCCESS(CmpAddSecurityCellToCache ( (PCMHIVE)Hive,NextCell,TRUE,NULL) ) ) {
|
||||
return FALSE;
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// just check this cell is there
|
||||
//
|
||||
ULONG Index;
|
||||
if( CmpFindSecurityCellCacheIndex ((PCMHIVE)Hive,NextCell,&Index) == FALSE ) {
|
||||
//
|
||||
// bad things happened; maybe an error in our caching code?
|
||||
//
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
LastCell = NextCell;
|
||||
NextCell = SecurityCell->Flink;
|
||||
} while ( NextCell != ListAnchor );
|
||||
|
||||
if( BuildSecurityCache == TRUE ) {
|
||||
//
|
||||
// adjust the size of the cache in case we allocated too much
|
||||
//
|
||||
CmpAdjustSecurityCacheSize ( (PCMHIVE)Hive );
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
141
base/ntos/config/cmclose.c
Normal file
141
base/ntos/config/cmclose.c
Normal file
@ -0,0 +1,141 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
cmclose.c
|
||||
|
||||
Abstract:
|
||||
|
||||
This module contains the close object method.
|
||||
|
||||
--*/
|
||||
|
||||
#include "cmp.h"
|
||||
|
||||
VOID
|
||||
CmpDelayedDerefKeys(
|
||||
PLIST_ENTRY DelayedDeref
|
||||
);
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE,CmpCloseKeyObject)
|
||||
#endif
|
||||
|
||||
VOID
|
||||
CmpCloseKeyObject(
|
||||
IN PEPROCESS Process OPTIONAL,
|
||||
IN PVOID Object,
|
||||
IN ACCESS_MASK GrantedAccess,
|
||||
IN ULONG_PTR ProcessHandleCount,
|
||||
IN ULONG_PTR SystemHandleCount
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine interfaces to the NT Object Manager. It is invoked when
|
||||
a Key object (or Key Root object) is closed.
|
||||
|
||||
It's function is to do cleanup processing by waking up any notifies
|
||||
pending on the handle. This keeps the key object from hanging around
|
||||
forever because a synchronous notify is stuck on it somewhere.
|
||||
|
||||
All other cleanup, in particular, the freeing of storage, will be
|
||||
done in CmpDeleteKeyObject.
|
||||
|
||||
Arguments:
|
||||
|
||||
Process - ignored
|
||||
|
||||
Object - supplies a pointer to a KeyRoot or Key, thus -> KEY_BODY.
|
||||
|
||||
GrantedAccess, ProcessHandleCount, SystemHandleCount - ignored
|
||||
|
||||
Return Value:
|
||||
|
||||
NONE.
|
||||
|
||||
--*/
|
||||
{
|
||||
PCM_KEY_BODY KeyBody;
|
||||
PCM_NOTIFY_BLOCK NotifyBlock;
|
||||
|
||||
CM_PAGED_CODE();
|
||||
|
||||
UNREFERENCED_PARAMETER (Process);
|
||||
UNREFERENCED_PARAMETER (GrantedAccess);
|
||||
UNREFERENCED_PARAMETER (ProcessHandleCount);
|
||||
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_POOL,"CmpCloseKeyObject: Object = %p\n", Object));
|
||||
|
||||
if( SystemHandleCount > 1 ) {
|
||||
//
|
||||
// There are still has open handles on this key. Do nothing
|
||||
//
|
||||
return;
|
||||
}
|
||||
|
||||
KeyBody = (PCM_KEY_BODY)Object;
|
||||
|
||||
//
|
||||
// Check the type, it will be something else if we are closing a predefined
|
||||
// handle key
|
||||
//
|
||||
if (KeyBody->Type == KEY_BODY_TYPE) {
|
||||
|
||||
if (KeyBody->NotifyBlock == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
CmpLockRegistry();
|
||||
|
||||
//
|
||||
// Clean up any outstanding notifies attached to the KeyBody
|
||||
//
|
||||
CmLockHive((PCMHIVE)(KeyBody->KeyControlBlock->KeyHive));
|
||||
if (KeyBody->NotifyBlock != NULL) {
|
||||
//
|
||||
// Post all PostBlocks waiting on the NotifyBlock
|
||||
//
|
||||
NotifyBlock = KeyBody->NotifyBlock;
|
||||
if (IsListEmpty(&(NotifyBlock->PostList)) == FALSE) {
|
||||
LIST_ENTRY DelayedDeref;
|
||||
//
|
||||
// we need to follow the rule here the hive lock
|
||||
// otherwise we could deadlock down in CmDeleteKeyObject. We don't acquire the kcb lock,
|
||||
// but we make sure that in subsequent places where we get the hive lock we get it before
|
||||
// the kcb lock, ie. we follow the precedence rule below.
|
||||
//
|
||||
// NB: the order of these locks is First the hive lock, then the kcb lock
|
||||
//
|
||||
InitializeListHead(&DelayedDeref);
|
||||
CmpPostNotify(NotifyBlock,
|
||||
NULL,
|
||||
0,
|
||||
STATUS_NOTIFY_CLEANUP,
|
||||
FALSE,
|
||||
&DelayedDeref
|
||||
#if DBG
|
||||
,(PCMHIVE)(KeyBody->KeyControlBlock->KeyHive)
|
||||
#endif
|
||||
);
|
||||
//
|
||||
// finish the job started in CmpPostNotify (i.e. dereference the keybodies
|
||||
// we prevented. this may cause some notifyblocks to be freed
|
||||
//
|
||||
CmpDelayedDerefKeys(&DelayedDeref);
|
||||
}
|
||||
}
|
||||
CmUnlockHive((PCMHIVE)(KeyBody->KeyControlBlock->KeyHive));
|
||||
|
||||
CmpUnlockRegistry();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
711
base/ntos/config/cmconfig.c
Normal file
711
base/ntos/config/cmconfig.c
Normal file
@ -0,0 +1,711 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
cmconfig.c
|
||||
|
||||
Abstract:
|
||||
|
||||
This module is responsible to build the hardware tree of the
|
||||
registry data base.
|
||||
|
||||
--*/
|
||||
|
||||
#include "cmp.h"
|
||||
|
||||
//
|
||||
// Title Index - Never used for Product 1, set to 0 for now.
|
||||
//
|
||||
|
||||
#define TITLE_INDEX_VALUE 0
|
||||
|
||||
|
||||
extern ULONG CmpTypeCount[];
|
||||
|
||||
|
||||
#define EISA_ADAPTER_INDEX EisaAdapter
|
||||
#define TURBOCHANNEL_ADAPTER_INDEX TcAdapter
|
||||
|
||||
//
|
||||
// The following variables are used to cross-reference multifunction
|
||||
// adapters to their corresponding NT interface type.
|
||||
//
|
||||
|
||||
extern struct {
|
||||
PUCHAR AscString;
|
||||
USHORT InterfaceType;
|
||||
USHORT Count;
|
||||
} CmpMultifunctionTypes[];
|
||||
|
||||
extern USHORT CmpUnknownBusCount;
|
||||
|
||||
|
||||
//
|
||||
// CmpConfigurationData - A pointer to the area reserved for the purpose
|
||||
// of reconstructing Configuration Data.
|
||||
//
|
||||
// CmpConfigurationAreaSize - Record the size of the Configuration Data
|
||||
// area.
|
||||
|
||||
extern ULONG CmpConfigurationAreaSize;
|
||||
extern PCM_FULL_RESOURCE_DESCRIPTOR CmpConfigurationData;
|
||||
|
||||
//
|
||||
// Function prototypes for internal references
|
||||
//
|
||||
|
||||
NTSTATUS
|
||||
CmpSetupConfigurationTree(
|
||||
IN PCONFIGURATION_COMPONENT_DATA CurrentEntry,
|
||||
IN HANDLE ParentHandle,
|
||||
IN INTERFACE_TYPE InterfaceType,
|
||||
IN ULONG BusNumber
|
||||
);
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(INIT,CmpInitializeHardwareConfiguration)
|
||||
#pragma alloc_text(INIT,CmpSetupConfigurationTree)
|
||||
#pragma alloc_text(INIT,CmpInitializeRegistryNode)
|
||||
#endif
|
||||
|
||||
|
||||
NTSTATUS
|
||||
CmpInitializeHardwareConfiguration(
|
||||
IN PLOADER_PARAMETER_BLOCK LoaderBlock
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine creates \\Registry\Machine\Hardware node in
|
||||
the registry and calls SetupTree routine to put the hardware
|
||||
information to the registry.
|
||||
|
||||
Arguments:
|
||||
|
||||
LoaderBlock - supplies a pointer to the LoaderBlock passed in from the
|
||||
OS Loader.
|
||||
|
||||
Returns:
|
||||
|
||||
NTSTATUS code for success or reason of failure.
|
||||
|
||||
--*/
|
||||
{
|
||||
NTSTATUS Status;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
HANDLE BaseHandle;
|
||||
PCONFIGURATION_COMPONENT_DATA ConfigurationRoot;
|
||||
ULONG Disposition;
|
||||
|
||||
ConfigurationRoot = (PCONFIGURATION_COMPONENT_DATA)LoaderBlock->ConfigurationRoot;
|
||||
|
||||
//
|
||||
// Create \\Registry\Machine\Hardware\DeviceMap
|
||||
//
|
||||
|
||||
InitializeObjectAttributes(
|
||||
&ObjectAttributes,
|
||||
&CmRegistryMachineHardwareDeviceMapName,
|
||||
0,
|
||||
(HANDLE)NULL,
|
||||
NULL
|
||||
);
|
||||
ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;
|
||||
|
||||
Status = NtCreateKey( // Paht may already exist
|
||||
&BaseHandle,
|
||||
KEY_READ | KEY_WRITE,
|
||||
&ObjectAttributes,
|
||||
TITLE_INDEX_VALUE,
|
||||
NULL,
|
||||
0,
|
||||
&Disposition
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
return(Status);
|
||||
}
|
||||
|
||||
NtClose(BaseHandle);
|
||||
|
||||
ASSERT(Disposition == REG_CREATED_NEW_KEY);
|
||||
|
||||
//
|
||||
// Create \\Registry\Machine\Hardware\Description and use the
|
||||
// returned handle as the BaseHandle to build the hardware tree.
|
||||
//
|
||||
|
||||
InitializeObjectAttributes(
|
||||
&ObjectAttributes,
|
||||
&CmRegistryMachineHardwareDescriptionName,
|
||||
0,
|
||||
(HANDLE)NULL,
|
||||
NULL
|
||||
);
|
||||
ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;
|
||||
|
||||
Status = NtCreateKey( // Path may already exist
|
||||
&BaseHandle,
|
||||
KEY_READ | KEY_WRITE,
|
||||
&ObjectAttributes,
|
||||
TITLE_INDEX_VALUE,
|
||||
NULL,
|
||||
0,
|
||||
&Disposition
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
return(Status);
|
||||
}
|
||||
|
||||
ASSERT(Disposition == REG_CREATED_NEW_KEY);
|
||||
|
||||
//
|
||||
// Allocate 16K bytes memory from paged pool for constructing
|
||||
// configuration data for controller component.
|
||||
// NOTE: The configuration Data for controller component
|
||||
// usually takes less than 100 bytes. But on EISA machine, the
|
||||
// EISA configuration information takes more than 10K and up to
|
||||
// 64K. I believe 16K is the reasonable number to handler 99.9%
|
||||
// of the machines. Therefore, 16K is the initial value.
|
||||
//
|
||||
|
||||
CmpConfigurationData = (PCM_FULL_RESOURCE_DESCRIPTOR)ExAllocatePool(
|
||||
PagedPool,
|
||||
CmpConfigurationAreaSize
|
||||
);
|
||||
|
||||
if (CmpConfigurationData == NULL) {
|
||||
return(STATUS_INSUFFICIENT_RESOURCES);
|
||||
}
|
||||
|
||||
//
|
||||
// Call SetupConfigurationTree routine to go over each component
|
||||
// of the tree and add component information to registry database.
|
||||
//
|
||||
|
||||
if (ConfigurationRoot) {
|
||||
Status = CmpSetupConfigurationTree(ConfigurationRoot,
|
||||
BaseHandle,
|
||||
-1,
|
||||
(ULONG)-1);
|
||||
} else {
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ExFreePool((PVOID)CmpConfigurationData);
|
||||
NtClose(BaseHandle);
|
||||
return(Status);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
CmpSetupConfigurationTree(
|
||||
IN PCONFIGURATION_COMPONENT_DATA CurrentEntry,
|
||||
IN HANDLE ParentHandle,
|
||||
IN INTERFACE_TYPE InterfaceType,
|
||||
IN ULONG BusNumber
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine traverses loader configuration tree and register
|
||||
the hardware information to the registry data base.
|
||||
|
||||
Note to reduce the stack usage on machines with large number of PCI buses,
|
||||
we do not recursively process the sibling nodes. We only recursively
|
||||
process the child trees.
|
||||
|
||||
Arguments:
|
||||
|
||||
CurrentEntry - Supplies a pointer to a loader configuration
|
||||
tree or subtree.
|
||||
|
||||
ParentHandle - Supplies the parent handle of CurrentEntry node.
|
||||
|
||||
InterfaceType - Specify the Interface type of the bus that the
|
||||
CurrentEntry component resides.
|
||||
|
||||
BusNumber - Specify the Bus Number of the bus that the CurrentEntry
|
||||
component resides. If Bus number is -1, it means InterfaceType
|
||||
and BusNumber are meaningless for this component.
|
||||
|
||||
Returns:
|
||||
|
||||
None.
|
||||
|
||||
--*/
|
||||
{
|
||||
NTSTATUS Status;
|
||||
HANDLE NewHandle;
|
||||
USHORT i;
|
||||
CONFIGURATION_COMPONENT *Component;
|
||||
INTERFACE_TYPE LocalInterfaceType = InterfaceType;
|
||||
ULONG LocalBusNumber = BusNumber;
|
||||
USHORT DeviceIndexTable[NUMBER_TYPES];
|
||||
|
||||
for (i = 0; i < NUMBER_TYPES; i++) {
|
||||
DeviceIndexTable[i] = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// Process current entry and its siblings
|
||||
//
|
||||
|
||||
while (CurrentEntry) {
|
||||
|
||||
//
|
||||
// Register current entry first before going down to its children
|
||||
//
|
||||
|
||||
Component = &CurrentEntry->ComponentEntry;
|
||||
|
||||
//
|
||||
// If the current component is a bus component, we will set up
|
||||
// its bus number and Interface type and use them to initialize
|
||||
// its subtree.
|
||||
//
|
||||
|
||||
if (Component->Class == AdapterClass &&
|
||||
CurrentEntry->Parent->ComponentEntry.Class == SystemClass) {
|
||||
|
||||
switch (Component->Type) {
|
||||
|
||||
case EisaAdapter:
|
||||
LocalInterfaceType = Eisa;
|
||||
LocalBusNumber = CmpTypeCount[EISA_ADAPTER_INDEX]++;
|
||||
break;
|
||||
case TcAdapter:
|
||||
LocalInterfaceType = TurboChannel;
|
||||
LocalBusNumber = CmpTypeCount[TURBOCHANNEL_ADAPTER_INDEX]++;
|
||||
break;
|
||||
case MultiFunctionAdapter:
|
||||
|
||||
//
|
||||
// Here we try to distinguish if the Multifunction adapter is
|
||||
// Isa, Mca, Internal bus and assign BusNumber based on
|
||||
// its interface type (bus type.)
|
||||
//
|
||||
|
||||
if (Component->Identifier) {
|
||||
for (i=0; CmpMultifunctionTypes[i].AscString; i++) {
|
||||
if (_stricmp((PCHAR)CmpMultifunctionTypes[i].AscString,
|
||||
Component->Identifier) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LocalInterfaceType = CmpMultifunctionTypes[i].InterfaceType;
|
||||
LocalBusNumber = CmpMultifunctionTypes[i].Count++;
|
||||
}
|
||||
break;
|
||||
|
||||
case ScsiAdapter:
|
||||
|
||||
//
|
||||
// Set the bus type to internal.
|
||||
//
|
||||
|
||||
LocalInterfaceType = Internal;
|
||||
LocalBusNumber = CmpTypeCount[ScsiAdapter]++;
|
||||
break;
|
||||
|
||||
default:
|
||||
LocalInterfaceType = -1;
|
||||
LocalBusNumber = CmpUnknownBusCount++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize and copy current component to hardware registry
|
||||
//
|
||||
|
||||
Status = CmpInitializeRegistryNode(
|
||||
CurrentEntry,
|
||||
ParentHandle,
|
||||
&NewHandle,
|
||||
LocalInterfaceType,
|
||||
LocalBusNumber,
|
||||
DeviceIndexTable
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
return(Status);
|
||||
}
|
||||
|
||||
//
|
||||
// Once we are going one level down, we need to clear the TypeCount
|
||||
// table for everything under the current component class ...
|
||||
//
|
||||
|
||||
if (CurrentEntry->Child) {
|
||||
|
||||
//
|
||||
// Process the child entry of current entry
|
||||
//
|
||||
|
||||
Status = CmpSetupConfigurationTree(CurrentEntry->Child,
|
||||
NewHandle,
|
||||
LocalInterfaceType,
|
||||
LocalBusNumber
|
||||
);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
NtClose(NewHandle);
|
||||
return(Status);
|
||||
}
|
||||
}
|
||||
NtClose(NewHandle);
|
||||
CurrentEntry = CurrentEntry->Sibling;
|
||||
}
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
CmpInitializeRegistryNode(
|
||||
IN PCONFIGURATION_COMPONENT_DATA CurrentEntry,
|
||||
IN HANDLE ParentHandle,
|
||||
OUT PHANDLE NewHandle,
|
||||
IN INTERFACE_TYPE InterfaceType,
|
||||
IN ULONG BusNumber,
|
||||
IN PUSHORT DeviceIndexTable
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine creates a node for the current firmware component
|
||||
and puts component data to the data part of the node.
|
||||
|
||||
Arguments:
|
||||
|
||||
CurrentEntry - Supplies a pointer to a configuration component.
|
||||
|
||||
Handle - Supplies the parent handle of CurrentEntry node.
|
||||
|
||||
NewHandle - Supplies a pointer to a HANDLE to receive the handle of
|
||||
the newly created node.
|
||||
|
||||
InterfaceType - Specify the Interface type of the bus that the
|
||||
CurrentEntry component resides. (See BusNumber also)
|
||||
|
||||
BusNumber - Specify the Bus Number of the bus that the CurrentEntry
|
||||
component resides on. If Bus number is -1, it means InterfaceType
|
||||
and BusNumber are meaningless for this component.
|
||||
|
||||
Returns:
|
||||
|
||||
None.
|
||||
|
||||
--*/
|
||||
{
|
||||
|
||||
NTSTATUS Status;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
UNICODE_STRING KeyName;
|
||||
UNICODE_STRING ValueName;
|
||||
UNICODE_STRING ValueData;
|
||||
HANDLE Handle;
|
||||
HANDLE OldHandle;
|
||||
ANSI_STRING AnsiString;
|
||||
CHAR Buffer[12];
|
||||
WCHAR UnicodeBuffer[12];
|
||||
CONFIGURATION_COMPONENT *Component;
|
||||
ULONG Disposition;
|
||||
ULONG ConfigurationDataLength = 0;
|
||||
PCM_FULL_RESOURCE_DESCRIPTOR NewArea;
|
||||
|
||||
Component = &CurrentEntry->ComponentEntry;
|
||||
|
||||
//
|
||||
// If the component class is SystemClass, we set its Type to be
|
||||
// ArcSystem. The reason is because the detection code sets
|
||||
// its type to MaximumType to indicate it is NOT ARC compatible.
|
||||
// Here, we are only interested in building a System Node. So we
|
||||
// change its Type to ArcSystem to ease the setup.
|
||||
//
|
||||
|
||||
if (Component->Class == SystemClass) {
|
||||
Component->Type = ArcSystem;
|
||||
}
|
||||
|
||||
//
|
||||
// Create a new key to describe the Component.
|
||||
//
|
||||
// The type of the component will be used as the keyname of the
|
||||
// registry node. The class is the class of the component.
|
||||
//
|
||||
|
||||
InitializeObjectAttributes(
|
||||
&ObjectAttributes,
|
||||
&(CmTypeName[Component->Type]),
|
||||
0,
|
||||
ParentHandle,
|
||||
NULL
|
||||
);
|
||||
ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;
|
||||
|
||||
Status = NtCreateKey( // Paht may already exist
|
||||
&Handle,
|
||||
KEY_READ | KEY_WRITE,
|
||||
&ObjectAttributes,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
&Disposition
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
return(Status);
|
||||
}
|
||||
|
||||
//
|
||||
// If this component is NOT a SystemClass component, we will
|
||||
// create a subkey to identify the component's ordering.
|
||||
//
|
||||
|
||||
if (Component->Class != SystemClass) {
|
||||
|
||||
RtlIntegerToChar(
|
||||
DeviceIndexTable[Component->Type]++,
|
||||
10,
|
||||
12,
|
||||
Buffer
|
||||
);
|
||||
|
||||
RtlInitAnsiString(
|
||||
&AnsiString,
|
||||
Buffer
|
||||
);
|
||||
|
||||
KeyName.Buffer = (PWSTR)UnicodeBuffer;
|
||||
KeyName.Length = 0;
|
||||
KeyName.MaximumLength = sizeof(UnicodeBuffer);
|
||||
|
||||
RtlAnsiStringToUnicodeString(
|
||||
&KeyName,
|
||||
&AnsiString,
|
||||
FALSE
|
||||
);
|
||||
|
||||
OldHandle = Handle;
|
||||
|
||||
InitializeObjectAttributes(
|
||||
&ObjectAttributes,
|
||||
&KeyName,
|
||||
0,
|
||||
OldHandle,
|
||||
NULL
|
||||
);
|
||||
ObjectAttributes.Attributes |= OBJ_CASE_INSENSITIVE;
|
||||
|
||||
Status = NtCreateKey(
|
||||
&Handle,
|
||||
KEY_READ | KEY_WRITE,
|
||||
&ObjectAttributes,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
&Disposition
|
||||
);
|
||||
|
||||
NtClose(OldHandle);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
return(Status);
|
||||
}
|
||||
|
||||
ASSERT(Disposition == REG_CREATED_NEW_KEY);
|
||||
}
|
||||
|
||||
//
|
||||
// Create a value which describes the following component information:
|
||||
// Flags, Cersion, Key, AffinityMask.
|
||||
//
|
||||
|
||||
RtlInitUnicodeString(
|
||||
&ValueName,
|
||||
L"Component Information"
|
||||
);
|
||||
|
||||
Status = NtSetValueKey(
|
||||
Handle,
|
||||
&ValueName,
|
||||
TITLE_INDEX_VALUE,
|
||||
REG_BINARY,
|
||||
&Component->Flags,
|
||||
FIELD_OFFSET(CONFIGURATION_COMPONENT, ConfigurationDataLength) -
|
||||
FIELD_OFFSET(CONFIGURATION_COMPONENT, Flags)
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
NtClose(Handle);
|
||||
return(Status);
|
||||
}
|
||||
|
||||
//
|
||||
// Create a value which describes the component identifier, if any.
|
||||
//
|
||||
|
||||
if (Component->IdentifierLength) {
|
||||
|
||||
RtlInitUnicodeString(
|
||||
&ValueName,
|
||||
L"Identifier"
|
||||
);
|
||||
|
||||
RtlInitAnsiString(
|
||||
&AnsiString,
|
||||
Component->Identifier
|
||||
);
|
||||
|
||||
Status = RtlAnsiStringToUnicodeString(
|
||||
&ValueData,
|
||||
&AnsiString,
|
||||
TRUE
|
||||
);
|
||||
|
||||
if( NT_SUCCESS(Status) ) {
|
||||
Status = NtSetValueKey(
|
||||
Handle,
|
||||
&ValueName,
|
||||
TITLE_INDEX_VALUE,
|
||||
REG_SZ,
|
||||
ValueData.Buffer,
|
||||
ValueData.Length + sizeof( UNICODE_NULL )
|
||||
);
|
||||
|
||||
RtlFreeUnicodeString(&ValueData);
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
NtClose(Handle);
|
||||
return(Status);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Create a value entry for component configuration data.
|
||||
//
|
||||
|
||||
RtlInitUnicodeString(
|
||||
&ValueName,
|
||||
L"Configuration Data"
|
||||
);
|
||||
|
||||
//
|
||||
// Create the configuration data based on CM_FULL_RESOURCE_DESCRIPTOR.
|
||||
//
|
||||
// Note the configuration data in firmware tree may be in the form of
|
||||
// CM_PARTIAL_RESOURCE_LIST or nothing. In both cases, we need to
|
||||
// set up the registry configuration data to be in the form of
|
||||
// CM_FULL_RESOURCE_DESCRIPTOR.
|
||||
//
|
||||
|
||||
if (CurrentEntry->ConfigurationData) {
|
||||
|
||||
//
|
||||
// This component has configuration data, we copy the data
|
||||
// to our work area, add some more data items and copy the new
|
||||
// configuration data to the registry.
|
||||
//
|
||||
|
||||
ConfigurationDataLength = Component->ConfigurationDataLength +
|
||||
FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR,
|
||||
PartialResourceList);
|
||||
|
||||
//
|
||||
// Make sure our reserved area is big enough to hold the data.
|
||||
//
|
||||
|
||||
if (ConfigurationDataLength > CmpConfigurationAreaSize) {
|
||||
|
||||
//
|
||||
// If reserved area is not big enough, we resize our reserved
|
||||
// area. If, unfortunately, the reallocation fails, we simply
|
||||
// loss the configuration data of this particular component.
|
||||
//
|
||||
|
||||
NewArea = (PCM_FULL_RESOURCE_DESCRIPTOR)ExAllocatePool(
|
||||
PagedPool,
|
||||
ConfigurationDataLength
|
||||
);
|
||||
|
||||
if (NewArea) {
|
||||
CmpConfigurationAreaSize = ConfigurationDataLength;
|
||||
ExFreePool(CmpConfigurationData);
|
||||
CmpConfigurationData = NewArea;
|
||||
RtlCopyMemory(
|
||||
(PUCHAR)&CmpConfigurationData->PartialResourceList.Version,
|
||||
CurrentEntry->ConfigurationData,
|
||||
Component->ConfigurationDataLength
|
||||
);
|
||||
} else {
|
||||
Component->ConfigurationDataLength = 0;
|
||||
CurrentEntry->ConfigurationData = NULL;
|
||||
}
|
||||
} else {
|
||||
RtlCopyMemory(
|
||||
(PUCHAR)&CmpConfigurationData->PartialResourceList.Version,
|
||||
CurrentEntry->ConfigurationData,
|
||||
Component->ConfigurationDataLength
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (CurrentEntry->ConfigurationData == NULL) {
|
||||
|
||||
//
|
||||
// This component has NO configuration data (or we can't resize
|
||||
// our reserved area to hold the data), we simple add whatever
|
||||
// is required to set up a CM_FULL_RESOURCE_LIST.
|
||||
//
|
||||
|
||||
CmpConfigurationData->PartialResourceList.Version = 0;
|
||||
CmpConfigurationData->PartialResourceList.Revision = 0;
|
||||
CmpConfigurationData->PartialResourceList.Count = 0;
|
||||
ConfigurationDataLength = FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR,
|
||||
PartialResourceList) +
|
||||
FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST,
|
||||
PartialDescriptors);
|
||||
}
|
||||
|
||||
//
|
||||
// Set up InterfaceType and BusNumber for the component.
|
||||
//
|
||||
|
||||
CmpConfigurationData->InterfaceType = InterfaceType;
|
||||
CmpConfigurationData->BusNumber = BusNumber;
|
||||
|
||||
//
|
||||
// Write the newly constructed configuration data to the hardware registry
|
||||
//
|
||||
|
||||
Status = NtSetValueKey(
|
||||
Handle,
|
||||
&ValueName,
|
||||
TITLE_INDEX_VALUE,
|
||||
REG_FULL_RESOURCE_DESCRIPTOR,
|
||||
CmpConfigurationData,
|
||||
ConfigurationDataLength
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
NtClose(Handle);
|
||||
return(Status);
|
||||
}
|
||||
|
||||
*NewHandle = Handle;
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
409
base/ntos/config/cmcontrl.c
Normal file
409
base/ntos/config/cmcontrl.c
Normal file
@ -0,0 +1,409 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
cmcontrl.c
|
||||
|
||||
Abstract:
|
||||
|
||||
The module contains CmGetSystemControlValues, see cmdat.c for data.
|
||||
|
||||
--*/
|
||||
|
||||
#include "cmp.h"
|
||||
|
||||
extern WCHAR CmDefaultLanguageId[];
|
||||
extern ULONG CmDefaultLanguageIdLength;
|
||||
extern ULONG CmDefaultLanguageIdType;
|
||||
|
||||
extern WCHAR CmInstallUILanguageId[];
|
||||
extern ULONG CmInstallUILanguageIdLength;
|
||||
extern ULONG CmInstallUILanguageIdType;
|
||||
|
||||
#ifdef ALLOC_DATA_PRAGMA
|
||||
#pragma data_seg("INITDATA")
|
||||
#endif
|
||||
CMHIVE CmControlHive;
|
||||
#ifdef ALLOC_DATA_PRAGMA
|
||||
#pragma data_seg()
|
||||
#endif
|
||||
|
||||
HCELL_INDEX
|
||||
CmpWalkPath(
|
||||
PHHIVE SystemHive,
|
||||
HCELL_INDEX ParentCell,
|
||||
PWSTR Path
|
||||
);
|
||||
|
||||
LANGID
|
||||
CmpConvertLangId(
|
||||
PWSTR LangIdString,
|
||||
ULONG LangIdStringLength
|
||||
);
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(INIT,CmGetSystemControlValues)
|
||||
#pragma alloc_text(INIT,CmpWalkPath)
|
||||
#pragma alloc_text(INIT,CmpConvertLangId)
|
||||
#endif
|
||||
|
||||
VOID
|
||||
CmGetSystemControlValues(
|
||||
__in PVOID SystemHiveBuffer,
|
||||
__inout PCM_SYSTEM_CONTROL_VECTOR ControlVector
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Look for registry values in current control set, as specified
|
||||
by entries in ControlVector. Report data for value entries
|
||||
(if any) to variables ControlVector points to.
|
||||
|
||||
Arguments:
|
||||
|
||||
SystemHiveBuffer - pointer to flat image of the system hive
|
||||
|
||||
ControlVector - pointer to structure that describes what values
|
||||
to pull out and store
|
||||
|
||||
Return Value:
|
||||
|
||||
NONE.
|
||||
|
||||
--*/
|
||||
{
|
||||
NTSTATUS status;
|
||||
PHHIVE SystemHive;
|
||||
HCELL_INDEX RootCell;
|
||||
HCELL_INDEX BaseCell;
|
||||
UNICODE_STRING Name;
|
||||
HCELL_INDEX KeyCell;
|
||||
HCELL_INDEX ValueCell;
|
||||
PCM_KEY_VALUE ValueBody;
|
||||
ULONG Length;
|
||||
BOOLEAN AutoSelect;
|
||||
BOOLEAN small;
|
||||
ULONG tmplength;
|
||||
PCM_KEY_NODE Node;
|
||||
|
||||
//
|
||||
// set up to read flat system hive image loader passes us
|
||||
//
|
||||
RtlZeroMemory((PVOID)&CmControlHive, sizeof(CmControlHive));
|
||||
SystemHive = &(CmControlHive.Hive);
|
||||
CmpInitHiveViewList((PCMHIVE)SystemHive);
|
||||
CmpInitSecurityCache((PCMHIVE)SystemHive);
|
||||
status = HvInitializeHive(
|
||||
SystemHive,
|
||||
HINIT_FLAT,
|
||||
HIVE_VOLATILE,
|
||||
HFILE_TYPE_PRIMARY,
|
||||
SystemHiveBuffer,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
1,
|
||||
NULL
|
||||
);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
CM_BUGCHECK(BAD_SYSTEM_CONFIG_INFO,BAD_SYSTEM_CONTROL_VALUES,1,SystemHive,status);
|
||||
}
|
||||
|
||||
//
|
||||
// don't bother locking/releasing cells
|
||||
//
|
||||
ASSERT( SystemHive->ReleaseCellRoutine == NULL );
|
||||
//
|
||||
// get hive.cell of root of current control set
|
||||
//
|
||||
RootCell = ((PHBASE_BLOCK)SystemHiveBuffer)->RootCell;
|
||||
RtlInitUnicodeString(&Name, L"current");
|
||||
BaseCell = CmpFindControlSet(
|
||||
SystemHive,
|
||||
RootCell,
|
||||
&Name,
|
||||
&AutoSelect
|
||||
);
|
||||
if (BaseCell == HCELL_NIL) {
|
||||
CM_BUGCHECK(BAD_SYSTEM_CONFIG_INFO,BAD_SYSTEM_CONTROL_VALUES,2,SystemHive,&Name);
|
||||
}
|
||||
|
||||
Node = (PCM_KEY_NODE)HvGetCell(SystemHive,BaseCell);
|
||||
if( Node == NULL ) {
|
||||
//
|
||||
// we couldn't map a view for the bin containing this cell
|
||||
//
|
||||
return;
|
||||
}
|
||||
RtlInitUnicodeString(&Name, L"control");
|
||||
BaseCell = CmpFindSubKeyByName(SystemHive,
|
||||
Node,
|
||||
&Name);
|
||||
if (BaseCell == HCELL_NIL) {
|
||||
CM_BUGCHECK(BAD_SYSTEM_CONFIG_INFO,BAD_SYSTEM_CONTROL_VALUES,3,Node,&Name);
|
||||
}
|
||||
|
||||
//
|
||||
// SystemHive.BaseCell = \registry\machine\system\currentcontrolset\control
|
||||
//
|
||||
|
||||
//
|
||||
// step through vector, trying to fetch each value
|
||||
//
|
||||
while (ControlVector->KeyPath != NULL) {
|
||||
|
||||
//
|
||||
// Assume we will fail to find the key or value.
|
||||
//
|
||||
|
||||
Length = (ULONG)-1;
|
||||
|
||||
KeyCell = CmpWalkPath(SystemHive, BaseCell, ControlVector->KeyPath);
|
||||
|
||||
if (KeyCell != HCELL_NIL) {
|
||||
|
||||
//
|
||||
// found the key, look for the value entry
|
||||
//
|
||||
Node = (PCM_KEY_NODE)HvGetCell(SystemHive,KeyCell);
|
||||
if( Node == NULL ) {
|
||||
//
|
||||
// we couldn't map a view for the bin containing this cell
|
||||
//
|
||||
return;
|
||||
}
|
||||
RtlInitUnicodeString(&Name, ControlVector->ValueName);
|
||||
ValueCell = CmpFindValueByName(SystemHive,
|
||||
Node,
|
||||
&Name);
|
||||
if (ValueCell != HCELL_NIL) {
|
||||
|
||||
//
|
||||
// SystemHive.ValueCell is value entry body
|
||||
//
|
||||
|
||||
if (ControlVector->BufferLength == NULL) {
|
||||
tmplength = sizeof(ULONG);
|
||||
} else {
|
||||
tmplength = *(ControlVector->BufferLength);
|
||||
}
|
||||
|
||||
ValueBody = (PCM_KEY_VALUE)HvGetCell(SystemHive, ValueCell);
|
||||
if( ValueBody == NULL ) {
|
||||
//
|
||||
// we couldn't map a view for the bin containing this cell
|
||||
//
|
||||
return;
|
||||
}
|
||||
|
||||
small = CmpIsHKeyValueSmall(Length, ValueBody->DataLength);
|
||||
|
||||
if (tmplength < Length) {
|
||||
Length = tmplength;
|
||||
}
|
||||
|
||||
if (Length > 0) {
|
||||
|
||||
PCELL_DATA Buffer;
|
||||
BOOLEAN BufferAllocated;
|
||||
ULONG realsize;
|
||||
HCELL_INDEX CellToRelease;
|
||||
|
||||
ASSERT((small ? (Length <= CM_KEY_VALUE_SMALL) : TRUE));
|
||||
//
|
||||
// get the data from source, regardless of the size
|
||||
//
|
||||
if( CmpGetValueData(SystemHive,ValueBody,&realsize,&Buffer,&BufferAllocated,&CellToRelease) == FALSE ) {
|
||||
//
|
||||
// insufficient resources; return NULL
|
||||
//
|
||||
ASSERT( BufferAllocated == FALSE );
|
||||
ASSERT( Buffer == NULL );
|
||||
return;
|
||||
}
|
||||
|
||||
RtlCopyMemory(
|
||||
ControlVector->Buffer,
|
||||
Buffer,
|
||||
Length
|
||||
);
|
||||
|
||||
//
|
||||
// cleanup the temporary buffer
|
||||
//
|
||||
if( BufferAllocated == TRUE ) {
|
||||
ExFreePool( Buffer );
|
||||
}
|
||||
if( CellToRelease != HCELL_NIL ) {
|
||||
HvReleaseCell(SystemHive,CellToRelease);
|
||||
}
|
||||
}
|
||||
|
||||
if (ControlVector->Type != NULL) {
|
||||
*(ControlVector->Type) = ValueBody->Type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Stash the length of result (-1 if nothing was found)
|
||||
//
|
||||
|
||||
if (ControlVector->BufferLength != NULL) {
|
||||
*(ControlVector->BufferLength) = Length;
|
||||
}
|
||||
|
||||
ControlVector++;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the default locale ID for the system from the registry.
|
||||
//
|
||||
|
||||
if (CmDefaultLanguageIdType == REG_SZ) {
|
||||
PsDefaultSystemLocaleId = (LCID) CmpConvertLangId(
|
||||
CmDefaultLanguageId,
|
||||
CmDefaultLanguageIdLength);
|
||||
} else {
|
||||
PsDefaultSystemLocaleId = 0x00000409;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the install (native UI) language ID for the system from the registry.
|
||||
//
|
||||
|
||||
if (CmInstallUILanguageIdType == REG_SZ) {
|
||||
PsInstallUILanguageId = CmpConvertLangId(
|
||||
CmInstallUILanguageId,
|
||||
CmInstallUILanguageIdLength);
|
||||
} else {
|
||||
PsInstallUILanguageId = LANGIDFROMLCID(PsDefaultSystemLocaleId);
|
||||
}
|
||||
|
||||
//
|
||||
// Set the default thread locale to the default system locale
|
||||
// for now. This will get changed as soon as somebody logs in.
|
||||
// Use the install (native) language id as our default UI language id.
|
||||
// This also will get changed as soon as somebody logs in.
|
||||
//
|
||||
|
||||
PsDefaultThreadLocaleId = PsDefaultSystemLocaleId;
|
||||
PsDefaultUILanguageId = PsInstallUILanguageId;
|
||||
}
|
||||
|
||||
|
||||
HCELL_INDEX
|
||||
CmpWalkPath(
|
||||
PHHIVE SystemHive,
|
||||
HCELL_INDEX ParentCell,
|
||||
PWSTR Path
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Walk the path.
|
||||
|
||||
Arguments:
|
||||
|
||||
SystemHive - hive
|
||||
|
||||
ParentCell - where to start
|
||||
|
||||
Path - string to walk
|
||||
|
||||
Return Value:
|
||||
|
||||
HCELL_INDEX of found key cell, or HCELL_NIL for error
|
||||
|
||||
--*/
|
||||
{
|
||||
UNICODE_STRING PathString;
|
||||
UNICODE_STRING NextName;
|
||||
BOOLEAN Last;
|
||||
HCELL_INDEX KeyCell;
|
||||
PCM_KEY_NODE Node;
|
||||
|
||||
//
|
||||
// don't bother counting/releasing used cells
|
||||
//
|
||||
ASSERT( SystemHive->ReleaseCellRoutine == NULL );
|
||||
|
||||
KeyCell = ParentCell;
|
||||
RtlInitUnicodeString(&PathString, Path);
|
||||
|
||||
while (TRUE) {
|
||||
|
||||
CmpGetNextName(&PathString, &NextName, &Last);
|
||||
|
||||
if (NextName.Length == 0) {
|
||||
return KeyCell;
|
||||
}
|
||||
|
||||
Node = (PCM_KEY_NODE)HvGetCell(SystemHive,KeyCell);
|
||||
if( Node == NULL ) {
|
||||
//
|
||||
// we couldn't map a view for the bin containing this cell
|
||||
//
|
||||
return HCELL_NIL;
|
||||
}
|
||||
KeyCell = CmpFindSubKeyByName(SystemHive,
|
||||
Node,
|
||||
&NextName);
|
||||
|
||||
if (KeyCell == HCELL_NIL) {
|
||||
return HCELL_NIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LANGID
|
||||
CmpConvertLangId(
|
||||
PWSTR LangIdString,
|
||||
ULONG LangIdStringLength
|
||||
)
|
||||
{
|
||||
|
||||
|
||||
USHORT i, Digit;
|
||||
WCHAR c;
|
||||
LANGID LangId;
|
||||
|
||||
LangId = 0;
|
||||
LangIdStringLength = LangIdStringLength / sizeof( WCHAR );
|
||||
for (i=0; i < LangIdStringLength; i++) {
|
||||
c = LangIdString[ i ];
|
||||
|
||||
if (c >= L'0' && c <= L'9') {
|
||||
Digit = c - L'0';
|
||||
|
||||
} else if (c >= L'A' && c <= L'F') {
|
||||
Digit = c - L'A' + 10;
|
||||
|
||||
} else if (c >= L'a' && c <= L'f') {
|
||||
Digit = c - L'a' + 10;
|
||||
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
if (Digit >= 16) {
|
||||
break;
|
||||
}
|
||||
|
||||
LangId = (LangId << 4) | Digit;
|
||||
}
|
||||
|
||||
return LangId;
|
||||
}
|
||||
|
||||
393
base/ntos/config/cmdat.c
Normal file
393
base/ntos/config/cmdat.c
Normal file
@ -0,0 +1,393 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
cmdat.c
|
||||
|
||||
Abstract:
|
||||
|
||||
This module contains registry "static" data, except for data
|
||||
also used by setup, which is in cmdat2.c.
|
||||
|
||||
--*/
|
||||
|
||||
#include "cmp.h"
|
||||
|
||||
//
|
||||
// ***** INIT *****
|
||||
//
|
||||
|
||||
#ifdef ALLOC_DATA_PRAGMA
|
||||
#pragma data_seg("INITDATA")
|
||||
#pragma const_seg("INITCONST")
|
||||
#endif
|
||||
|
||||
//
|
||||
// ---------------------------
|
||||
//
|
||||
|
||||
|
||||
UNICODE_STRING CmpLoadOptions = { 0 }; // sys options from FW or boot.ini
|
||||
|
||||
|
||||
//
|
||||
// CmpClassString - contains strings which are used as the class
|
||||
// strings in the keynode.
|
||||
// The associated enumerated type is CONFIGURATION_CLASS in arc.h
|
||||
//
|
||||
|
||||
UNICODE_STRING CmClassName[MaximumClass + 1] = { 0 };
|
||||
|
||||
const PWCHAR CmClassString[MaximumClass + 1] = {
|
||||
L"System",
|
||||
L"Processor",
|
||||
L"Cache",
|
||||
L"Adapter",
|
||||
L"Controller",
|
||||
L"Peripheral",
|
||||
L"MemoryClass",
|
||||
L"Undefined"
|
||||
};
|
||||
|
||||
|
||||
struct {
|
||||
PCHAR AscString;
|
||||
USHORT InterfaceType;
|
||||
USHORT Count;
|
||||
} CmpMultifunctionTypes[] = {
|
||||
"ISA", Isa, 0,
|
||||
"MCA", MicroChannel, 0,
|
||||
"PCI", PCIBus, 0,
|
||||
"VME", VMEBus, 0,
|
||||
"PCMCIA", PCMCIABus, 0,
|
||||
"CBUS", CBus, 0,
|
||||
"MPIPI", MPIBus, 0,
|
||||
"MPSA", MPSABus, 0,
|
||||
NULL, Internal, 0
|
||||
};
|
||||
|
||||
|
||||
USHORT CmpUnknownBusCount = 0;
|
||||
|
||||
ULONG CmpConfigurationAreaSize = 0x4000; // Initialize size = 16K
|
||||
PCM_FULL_RESOURCE_DESCRIPTOR CmpConfigurationData = { 0 };
|
||||
|
||||
//
|
||||
// The following strings will be used as the keynames for registry
|
||||
// nodes.
|
||||
// The associated enumerated type is CONFIGURATION_TYPE in arc.h
|
||||
//
|
||||
|
||||
UNICODE_STRING CmTypeName[MaximumType + 1] = { 0 };
|
||||
|
||||
|
||||
//
|
||||
// ***** PAGE *****
|
||||
//
|
||||
|
||||
#ifdef ALLOC_DATA_PRAGMA
|
||||
#pragma data_seg("PAGEDATA")
|
||||
#pragma const_seg("PAGECONST")
|
||||
#endif
|
||||
|
||||
const PWCHAR CmTypeString[MaximumType + 1] = {
|
||||
L"System",
|
||||
L"CentralProcessor",
|
||||
L"FloatingPointProcessor",
|
||||
L"PrimaryICache",
|
||||
L"PrimaryDCache",
|
||||
L"SecondaryICache",
|
||||
L"SecondaryDCache",
|
||||
L"SecondaryCache",
|
||||
L"EisaAdapter",
|
||||
L"TcAdapter",
|
||||
L"ScsiAdapter",
|
||||
L"DtiAdapter",
|
||||
L"MultifunctionAdapter",
|
||||
L"DiskController",
|
||||
L"TapeController",
|
||||
L"CdRomController",
|
||||
L"WormController",
|
||||
L"SerialController",
|
||||
L"NetworkController",
|
||||
L"DisplayController",
|
||||
L"ParallelController",
|
||||
L"PointerController",
|
||||
L"KeyboardController",
|
||||
L"AudioController",
|
||||
L"OtherController",
|
||||
L"DiskPeripheral",
|
||||
L"FloppyDiskPeripheral",
|
||||
L"TapePeripheral",
|
||||
L"ModemPeripheral",
|
||||
L"MonitorPeripheral",
|
||||
L"PrinterPeripheral",
|
||||
L"PointerPeripheral",
|
||||
L"KeyboardPeripheral",
|
||||
L"TerminalPeripheral",
|
||||
L"OtherPeripheral",
|
||||
L"LinePeripheral",
|
||||
L"NetworkPeripheral",
|
||||
L"SystemMemory",
|
||||
L"DockingInformation",
|
||||
L"RealModeIrqRoutingTable",
|
||||
L"RealModePCIEnumeration",
|
||||
L"Undefined"
|
||||
};
|
||||
|
||||
//
|
||||
// CmpTypeCount[] - For each 'type', a count is used to keep track how many
|
||||
// keys have been created.
|
||||
//
|
||||
|
||||
ULONG CmpTypeCount[NUMBER_TYPES] = {
|
||||
0, // ArcSystem
|
||||
0, // CentralProcessor",
|
||||
0, // FloatingPointProcessor",
|
||||
0, // PrimaryICache",
|
||||
0, // PrimaryDCache",
|
||||
0, // SecondaryICache",
|
||||
0, // SecondaryDCache",
|
||||
0, // SecondaryCache",
|
||||
0, // EisaAdapter", (8)
|
||||
0, // TcAdapter", (9)
|
||||
0, // ScsiAdapter",
|
||||
0, // DtiAdapter",
|
||||
0, // MultifunctionAdapter", (12)
|
||||
0, // DiskController", (13)
|
||||
0, // TapeController",
|
||||
0, // CdRomController",
|
||||
0, // WormController",
|
||||
0, // SerialController",
|
||||
0, // NetworkController",
|
||||
0, // DisplayController",
|
||||
0, // ParallelController",
|
||||
0, // PointerController",
|
||||
0, // KeyboardController",
|
||||
0, // AudioController",
|
||||
0, // OtherController",
|
||||
0, // DiskPeripheral",
|
||||
0, // FloppyDiskPeripheral",
|
||||
0, // TapePeripheral",
|
||||
0, // ModemPeripheral",
|
||||
0, // MonitorPeripheral",
|
||||
0, // PrinterPeripheral",
|
||||
0, // PointerPeripheral",
|
||||
0, // KeyboardPeripheral",
|
||||
0, // TerminalPeripheral",
|
||||
0, // OtherPeripheral",
|
||||
0, // LinePeripheral",
|
||||
0, // NetworkPeripheral",
|
||||
0, // SystemMemory",
|
||||
0, // DockingInformation,
|
||||
0, // RealModeIrqRoutingTable
|
||||
0 // Undefined"
|
||||
};
|
||||
|
||||
const UNICODE_STRING nullclass = { 0, 0, NULL };
|
||||
|
||||
//
|
||||
// All names used by the registry
|
||||
//
|
||||
|
||||
|
||||
UNICODE_STRING CmRegistryRootName = { 0 };
|
||||
UNICODE_STRING CmRegistryMachineName = { 0 };
|
||||
UNICODE_STRING CmRegistryMachineHardwareName = { 0 };
|
||||
UNICODE_STRING CmRegistryMachineHardwareDescriptionName = { 0 };
|
||||
UNICODE_STRING CmRegistryMachineHardwareDescriptionSystemName = { 0 };
|
||||
UNICODE_STRING CmRegistryMachineHardwareDeviceMapName = { 0 };
|
||||
UNICODE_STRING CmRegistryMachineHardwareResourceMapName = { 0 };
|
||||
UNICODE_STRING CmRegistryMachineHardwareOwnerMapName = { 0 };
|
||||
UNICODE_STRING CmRegistryMachineSystemName = { 0 };
|
||||
UNICODE_STRING CmRegistryMachineSystemCurrentControlSet = { 0 };
|
||||
UNICODE_STRING CmRegistryMachineSystemCurrentControlSetEnumName = { 0 };
|
||||
UNICODE_STRING CmRegistryMachineSystemCurrentControlSetEnumRootName = { 0 };
|
||||
UNICODE_STRING CmRegistryMachineSystemCurrentControlSetServices = { 0 };
|
||||
UNICODE_STRING CmRegistryMachineSystemCurrentControlSetHardwareProfilesCurrent = { 0 };
|
||||
UNICODE_STRING CmRegistryMachineSystemCurrentControlSetControlClass = { 0 };
|
||||
UNICODE_STRING CmRegistryMachineSystemCurrentControlSetControlSafeBoot = { 0 };
|
||||
UNICODE_STRING CmRegistryMachineSystemCurrentControlSetControlSessionManagerMemoryManagement = { 0 };
|
||||
UNICODE_STRING CmRegistryMachineSystemCurrentControlSetControlBootLog = { 0 };
|
||||
UNICODE_STRING CmRegistryMachineSystemCurrentControlSetServicesEventLog = { 0 };
|
||||
UNICODE_STRING CmRegistryUserName = { 0 };
|
||||
UNICODE_STRING CmRegistrySystemCloneName = { 0 };
|
||||
UNICODE_STRING CmpSystemFileName = { 0 };
|
||||
UNICODE_STRING CmSymbolicLinkValueName = { 0 };
|
||||
|
||||
#ifdef _WANT_MACHINE_IDENTIFICATION
|
||||
UNICODE_STRING CmRegistryMachineSystemCurrentControlSetControlBiosInfo = { 0 };
|
||||
#endif
|
||||
|
||||
const PWCHAR CmpRegistryRootString = L"\\REGISTRY";
|
||||
const PWCHAR CmpRegistryMachineString = L"\\REGISTRY\\MACHINE";
|
||||
const PWCHAR CmpRegistryMachineHardwareString =
|
||||
L"\\REGISTRY\\MACHINE\\HARDWARE";
|
||||
const PWCHAR CmpRegistryMachineHardwareDescriptionString =
|
||||
L"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION";
|
||||
const PWCHAR CmpRegistryMachineHardwareDescriptionSystemString =
|
||||
L"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM";
|
||||
const PWCHAR CmpRegistryMachineHardwareDeviceMapString =
|
||||
L"\\REGISTRY\\MACHINE\\HARDWARE\\DEVICEMAP";
|
||||
const PWCHAR CmpRegistryMachineHardwareResourceMapString =
|
||||
L"\\REGISTRY\\MACHINE\\HARDWARE\\RESOURCEMAP";
|
||||
const PWCHAR CmpRegistryMachineHardwareOwnerMapString =
|
||||
L"\\REGISTRY\\MACHINE\\HARDWARE\\OWNERMAP";
|
||||
const PWCHAR CmpRegistryMachineSystemString =
|
||||
L"\\REGISTRY\\MACHINE\\SYSTEM";
|
||||
const PWCHAR CmpRegistryMachineSystemCurrentControlSetString =
|
||||
L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET";
|
||||
const PWCHAR CmpRegistryMachineSystemCurrentControlSetEnumString =
|
||||
L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\ENUM";
|
||||
const PWCHAR CmpRegistryMachineSystemCurrentControlSetEnumRootString =
|
||||
L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\ENUM\\ROOT";
|
||||
const PWCHAR CmpRegistryMachineSystemCurrentControlSetServicesString =
|
||||
L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\SERVICES";
|
||||
const PWCHAR CmpRegistryMachineSystemCurrentControlSetHardwareProfilesCurrentString =
|
||||
L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\HARDWARE PROFILES\\CURRENT";
|
||||
const PWCHAR CmpRegistryMachineSystemCurrentControlSetControlClassString =
|
||||
L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\CONTROL\\CLASS";
|
||||
const PWCHAR CmpRegistryMachineSystemCurrentControlSetControlSafeBootString =
|
||||
L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\CONTROL\\SAFEBOOT";
|
||||
const PWCHAR CmpRegistryMachineSystemCurrentControlSetControlSessionManagerMemoryManagementString =
|
||||
L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\CONTROL\\SESSION MANAGER\\MEMORY MANAGEMENT";
|
||||
const PWCHAR CmpRegistryMachineSystemCurrentControlSetControlBootLogString =
|
||||
L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\CONTROL\\BOOTLOG";
|
||||
const PWCHAR CmpRegistryMachineSystemCurrentControlSetServicesEventLogString =
|
||||
L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\SERVICES\\EVENTLOG";
|
||||
const PWCHAR CmpRegistryUserString = L"\\REGISTRY\\USER";
|
||||
const PWCHAR CmpRegistrySystemCloneString = L"\\REGISTRY\\MACHINE\\CLONE";
|
||||
const PWCHAR CmpRegistrySystemFileNameString = L"SYSTEM";
|
||||
const PWCHAR CmpRegistryPerflibString = L"\\REGISTRY\\MACHINE\\SOFTWARE\\MICROSOFT\\WINDOWS NT\\CURRENTVERSION\\PERFLIB";
|
||||
|
||||
const PWCHAR CmpProcessorControl = L"ProcessorControl";
|
||||
const PWCHAR CmpControlSessionManager = L"Control\\Session Manager";
|
||||
const PWCHAR CmpSymbolicLinkValueName = L"SymbolicLinkValue";
|
||||
|
||||
#ifdef _WANT_MACHINE_IDENTIFICATION
|
||||
const PWCHAR CmpRegistryMachineSystemCurrentControlSetControlBiosInfoString =
|
||||
L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\CONTROL\\BIOSINFO";
|
||||
#endif
|
||||
|
||||
//
|
||||
// N.B. The CLONE hive is left out of the machine Hive list if
|
||||
// we will not be using it to clone the current control set,
|
||||
// since that is that Hive's only purpose.
|
||||
//
|
||||
|
||||
HIVE_LIST_ENTRY CmpMachineHiveList[] = {
|
||||
{ L"HARDWARE", L"MACHINE\\", NULL, HIVE_VOLATILE , 0 , NULL, FALSE, FALSE, FALSE},
|
||||
{ L"SECURITY", L"MACHINE\\", NULL, 0 , 0 , NULL, FALSE, FALSE, FALSE},
|
||||
{ L"SOFTWARE", L"MACHINE\\", NULL, 0 , 0 , NULL, FALSE, FALSE, FALSE},
|
||||
{ L"SYSTEM", L"MACHINE\\", NULL, 0 , 0 , NULL, FALSE, FALSE, FALSE},
|
||||
{ L"DEFAULT", L"USER\\.DEFAULT", NULL, 0 , CM_CMHIVE_FLAG_UNTRUSTED , NULL, FALSE, FALSE, FALSE},
|
||||
{ L"SAM", L"MACHINE\\", NULL, HIVE_NOLAZYFLUSH , 0 , NULL, FALSE, FALSE, FALSE},
|
||||
{ NULL, NULL, 0, 0 , 0 , NULL, FALSE, FALSE, FALSE}
|
||||
};
|
||||
|
||||
|
||||
UCHAR SystemHiveFullPathBuffer[MAX_NAME];
|
||||
UNICODE_STRING SystemHiveFullPathName;
|
||||
|
||||
//
|
||||
// Master Hive
|
||||
//
|
||||
// The KEY_NODEs for \REGISTRY, \REGISTRY\MACHINE, and \REGISTRY\USER
|
||||
// are stored in a small memory only hive called the Master Hive.
|
||||
// All other hives have link nodes in this hive which point to them.
|
||||
//
|
||||
PCMHIVE CmpMasterHive = { 0 };
|
||||
BOOLEAN CmpNoMasterCreates = FALSE; // Set TRUE after we're done to
|
||||
// prevent random creates in the
|
||||
// master hive, which is not backed
|
||||
// by a file.
|
||||
|
||||
|
||||
LIST_ENTRY CmpHiveListHead = { 0 }; // List of CMHIVEs
|
||||
EX_PUSH_LOCK CmpHiveListHeadLock; // used to protect the list above
|
||||
EX_PUSH_LOCK CmpLoadHiveLock;
|
||||
|
||||
//
|
||||
// Addresses of object type descriptors:
|
||||
//
|
||||
|
||||
POBJECT_TYPE CmpKeyObjectType = { 0 };
|
||||
|
||||
//
|
||||
// Write-Control:
|
||||
// CmpNoWrite is initially true. When set this way write and flush
|
||||
// do nothing, simply returning success. When cleared to FALSE, I/O
|
||||
// is enabled. This change is made after the I/O system is started
|
||||
// AND autocheck (chkdsk) has done its thing.
|
||||
//
|
||||
|
||||
BOOLEAN CmpNoWrite = TRUE;
|
||||
|
||||
|
||||
//
|
||||
// NtInitializeRegistry global status flags
|
||||
//
|
||||
|
||||
//
|
||||
// If CmFirstTime is TRUE, then NtInitializeRegistry has not yet been
|
||||
// called to perform basic registry initialization
|
||||
//
|
||||
|
||||
BOOLEAN CmFirstTime = TRUE;
|
||||
|
||||
//
|
||||
// trick to allow parallel threads to access the registry
|
||||
//
|
||||
BOOLEAN CmpSpecialBootCondition = FALSE;
|
||||
|
||||
|
||||
//
|
||||
// If CmBootAcceptFirstTime is TRUE, then NtInitializeRegistry has not
|
||||
// yet been called to accept the current Boot and save the boot
|
||||
// control set as the LKG control set.
|
||||
//
|
||||
|
||||
BOOLEAN CmBootAcceptFirstTime = TRUE;
|
||||
|
||||
//
|
||||
// CmpWasSetupBoot indicates whether or not the boot
|
||||
// is into text mode setup. If so, we do not turn
|
||||
// on global quotas.
|
||||
//
|
||||
BOOLEAN CmpWasSetupBoot;
|
||||
|
||||
//
|
||||
// Indicates whether the hives need to be loaded in memory
|
||||
// and in scratch mode
|
||||
//
|
||||
BOOLEAN CmpMiniNTBoot = FALSE;
|
||||
|
||||
//
|
||||
// Indicates whether the system hives need to be opened in a
|
||||
// shared mode. Generally needed if we are booting WinPE (MiniNT)
|
||||
// on network
|
||||
//
|
||||
BOOLEAN CmpShareSystemHives = FALSE;
|
||||
|
||||
//
|
||||
// Where are we booting from
|
||||
//
|
||||
ULONG CmpBootType;
|
||||
|
||||
//
|
||||
// Self healing hives control switch
|
||||
//
|
||||
BOOLEAN CmpSelfHeal = TRUE;
|
||||
|
||||
|
||||
#ifdef ALLOC_DATA_PRAGMA
|
||||
#pragma const_seg()
|
||||
#pragma data_seg()
|
||||
#endif
|
||||
|
||||
151
base/ntos/config/cmdat2.c
Normal file
151
base/ntos/config/cmdat2.c
Normal file
@ -0,0 +1,151 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
cmdat2.c
|
||||
|
||||
Abstract:
|
||||
|
||||
This module contains data strings that describes the registry space
|
||||
and that are exported to the rest of the system.
|
||||
|
||||
--*/
|
||||
|
||||
#include "cmp.h"
|
||||
|
||||
//
|
||||
// ***** PAGE *****
|
||||
//
|
||||
|
||||
#ifdef ALLOC_DATA_PRAGMA
|
||||
#pragma data_seg("PAGEDATA")
|
||||
#endif
|
||||
|
||||
//
|
||||
// control values/overrides read from registry
|
||||
//
|
||||
ULONG CmRegistrySizeLimit = { 0 };
|
||||
ULONG CmRegistrySizeLimitLength = 4;
|
||||
ULONG CmRegistrySizeLimitType = { 0 };
|
||||
|
||||
//
|
||||
// Maximum number of bytes of Global Quota the registry may use.
|
||||
// Set to largest positive number for use in boot. Will be set down
|
||||
// based on pool and explicit registry values.
|
||||
//
|
||||
SIZE_T CmpGlobalQuotaAllowed = CM_WRAP_LIMIT;
|
||||
SIZE_T CmpGlobalQuota = CM_WRAP_LIMIT;
|
||||
SIZE_T CmpGlobalQuotaWarning = CM_WRAP_LIMIT;
|
||||
BOOLEAN CmpQuotaWarningPopupDisplayed = FALSE;
|
||||
BOOLEAN CmpSystemQuotaWarningPopupDisplayed = FALSE;
|
||||
|
||||
//
|
||||
// the "disk full" popup has already been displayed
|
||||
//
|
||||
BOOLEAN CmpDiskFullWorkerPopupDisplayed = FALSE;
|
||||
BOOLEAN CmpCannotWriteConfiguration = FALSE;
|
||||
|
||||
//
|
||||
// GQ actually in use
|
||||
//
|
||||
SIZE_T CmpGlobalQuotaUsed = 0;
|
||||
|
||||
//
|
||||
// State flag to remember when to turn it on
|
||||
//
|
||||
BOOLEAN CmpProfileLoaded = FALSE;
|
||||
|
||||
PUCHAR CmpStashBuffer = NULL;
|
||||
ULONG CmpStashBufferSize = 0;
|
||||
EX_PUSH_LOCK CmpStashBufferLock;
|
||||
|
||||
//
|
||||
// Shutdown control
|
||||
//
|
||||
BOOLEAN HvShutdownComplete = FALSE; // Set to true after shutdown
|
||||
// to disable any further I/O
|
||||
|
||||
PCM_KEY_CONTROL_BLOCK CmpKeyControlBlockRoot = NULL;
|
||||
|
||||
HANDLE CmpRegistryRootHandle = NULL;
|
||||
|
||||
struct {
|
||||
PHHIVE Hive;
|
||||
ULONG Status;
|
||||
} CmCheckRegistryDebug = { 0 };
|
||||
|
||||
//
|
||||
// The last I/O error status code
|
||||
//
|
||||
struct {
|
||||
ULONG Action;
|
||||
HANDLE Handle;
|
||||
NTSTATUS Status;
|
||||
} CmRegistryIODebug = { 0 };
|
||||
|
||||
//
|
||||
// globals private to check code
|
||||
//
|
||||
|
||||
struct {
|
||||
PHHIVE Hive;
|
||||
ULONG Status;
|
||||
} CmpCheckRegistry2Debug = { 0 };
|
||||
|
||||
struct {
|
||||
PHHIVE Hive;
|
||||
ULONG Status;
|
||||
HCELL_INDEX Cell;
|
||||
PCELL_DATA CellPoint;
|
||||
PVOID RootPoint;
|
||||
ULONG Index;
|
||||
} CmpCheckKeyDebug = { 0 };
|
||||
|
||||
struct {
|
||||
PHHIVE Hive;
|
||||
ULONG Status;
|
||||
PCELL_DATA List;
|
||||
ULONG Index;
|
||||
HCELL_INDEX Cell;
|
||||
PCELL_DATA CellPoint;
|
||||
} CmpCheckValueListDebug = { 0 };
|
||||
|
||||
ULONG CmpUsedStorage = { 0 };
|
||||
|
||||
// hivechek.c
|
||||
struct {
|
||||
PHHIVE Hive;
|
||||
ULONG Status;
|
||||
ULONG Space;
|
||||
HCELL_INDEX MapPoint;
|
||||
PHBIN BinPoint;
|
||||
} HvCheckHiveDebug = { 0 };
|
||||
|
||||
struct {
|
||||
PHBIN Bin;
|
||||
ULONG Status;
|
||||
PHCELL CellPoint;
|
||||
} HvCheckBinDebug = { 0 };
|
||||
|
||||
struct {
|
||||
PHHIVE Hive;
|
||||
ULONG FileOffset;
|
||||
ULONG FailPoint; // look in HvpRecoverData for exact point of failure
|
||||
} HvRecoverDataDebug = { 0 };
|
||||
|
||||
//
|
||||
// when a local hive cannot be loaded, set this to it's index
|
||||
// and the load hive worker thread responsible for it will be held of
|
||||
// until all the others finish; We can then debug the offending hive
|
||||
//
|
||||
ULONG CmpCheckHiveIndex = CM_NUMBER_OF_MACHINE_HIVES;
|
||||
|
||||
#ifdef ALLOC_DATA_PRAGMA
|
||||
#pragma data_seg()
|
||||
#endif
|
||||
200
base/ntos/config/cmdatini.c
Normal file
200
base/ntos/config/cmdatini.c
Normal file
@ -0,0 +1,200 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
cmdatini.c
|
||||
|
||||
Abstract:
|
||||
|
||||
contains code to init static STRING structures for registry name space.
|
||||
|
||||
--*/
|
||||
|
||||
#include "cmp.h"
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(INIT,CmpInitializeRegistryNames)
|
||||
#endif
|
||||
|
||||
extern UNICODE_STRING CmRegistryRootName;
|
||||
extern UNICODE_STRING CmRegistryMachineName;
|
||||
extern UNICODE_STRING CmRegistryMachineHardwareName;
|
||||
extern UNICODE_STRING CmRegistryMachineHardwareDescriptionName;
|
||||
extern UNICODE_STRING CmRegistryMachineHardwareDescriptionSystemName;
|
||||
extern UNICODE_STRING CmRegistryMachineHardwareDeviceMapName;
|
||||
extern UNICODE_STRING CmRegistryMachineHardwareResourceMapName;
|
||||
extern UNICODE_STRING CmRegistryMachineHardwareOwnerMapName;
|
||||
extern UNICODE_STRING CmRegistryMachineSystemName;
|
||||
extern UNICODE_STRING CmRegistryMachineSystemCurrentControlSet;
|
||||
extern UNICODE_STRING CmRegistryUserName;
|
||||
extern UNICODE_STRING CmRegistrySystemCloneName;
|
||||
extern UNICODE_STRING CmpSystemFileName;
|
||||
extern UNICODE_STRING CmRegistryMachineSystemCurrentControlSetEnumName;
|
||||
extern UNICODE_STRING CmRegistryMachineSystemCurrentControlSetEnumRootName;
|
||||
extern UNICODE_STRING CmRegistryMachineSystemCurrentControlSetServices;
|
||||
extern UNICODE_STRING CmRegistryMachineSystemCurrentControlSetHardwareProfilesCurrent;
|
||||
extern UNICODE_STRING CmRegistryMachineSystemCurrentControlSetControlClass;
|
||||
extern UNICODE_STRING CmSymbolicLinkValueName;
|
||||
|
||||
#ifdef _WANT_MACHINE_IDENTIFICATION
|
||||
extern UNICODE_STRING CmRegistryMachineSystemCurrentControlSetControlBiosInfo;
|
||||
#endif
|
||||
|
||||
extern const PWCHAR CmpRegistryRootString;
|
||||
extern const PWCHAR CmpRegistryMachineString;
|
||||
extern const PWCHAR CmpRegistryMachineHardwareString;
|
||||
extern const PWCHAR CmpRegistryMachineHardwareDescriptionString;
|
||||
extern const PWCHAR CmpRegistryMachineHardwareDescriptionSystemString;
|
||||
extern const PWCHAR CmpRegistryMachineHardwareDeviceMapString;
|
||||
extern const PWCHAR CmpRegistryMachineHardwareResourceMapString;
|
||||
extern const PWCHAR CmpRegistryMachineHardwareOwnerMapString;
|
||||
extern const PWCHAR CmpRegistryMachineSystemString;
|
||||
extern const PWCHAR CmpRegistryMachineSystemCurrentControlSetString;
|
||||
extern const PWCHAR CmpRegistryUserString;
|
||||
extern const PWCHAR CmpRegistrySystemCloneString;
|
||||
extern const PWCHAR CmpRegistrySystemFileNameString;
|
||||
extern const PWCHAR CmpRegistryMachineSystemCurrentControlSetEnumString;
|
||||
extern const PWCHAR CmpRegistryMachineSystemCurrentControlSetEnumRootString;
|
||||
extern const PWCHAR CmpRegistryMachineSystemCurrentControlSetServicesString;
|
||||
extern const PWCHAR CmpRegistryMachineSystemCurrentControlSetHardwareProfilesCurrentString;
|
||||
extern const PWCHAR CmpRegistryMachineSystemCurrentControlSetControlClassString;
|
||||
extern const PWCHAR CmpRegistryMachineSystemCurrentControlSetControlSafeBootString;
|
||||
extern const PWCHAR CmpRegistryMachineSystemCurrentControlSetControlSessionManagerMemoryManagementString;
|
||||
|
||||
extern const PWCHAR CmpRegistryMachineSystemCurrentControlSetControlBootLogString;
|
||||
extern const PWCHAR CmpRegistryMachineSystemCurrentControlSetServicesEventLogString;
|
||||
extern const PWCHAR CmpSymbolicLinkValueName;
|
||||
|
||||
#ifdef _WANT_MACHINE_IDENTIFICATION
|
||||
extern const PWCHAR CmpRegistryMachineSystemCurrentControlSetControlBiosInfoString;
|
||||
#endif
|
||||
|
||||
|
||||
VOID
|
||||
CmpInitializeRegistryNames(
|
||||
VOID
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine creates all the Unicode strings for the various names used
|
||||
in and by the registry
|
||||
|
||||
Arguments:
|
||||
|
||||
None.
|
||||
|
||||
Returns:
|
||||
|
||||
None.
|
||||
|
||||
--*/
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
RtlInitUnicodeString( &CmRegistryRootName,
|
||||
CmpRegistryRootString );
|
||||
|
||||
RtlInitUnicodeString( &CmRegistryMachineName,
|
||||
CmpRegistryMachineString );
|
||||
|
||||
RtlInitUnicodeString( &CmRegistryMachineHardwareName,
|
||||
CmpRegistryMachineHardwareString );
|
||||
|
||||
RtlInitUnicodeString( &CmRegistryMachineHardwareDescriptionName,
|
||||
CmpRegistryMachineHardwareDescriptionString );
|
||||
|
||||
RtlInitUnicodeString( &CmRegistryMachineHardwareDescriptionSystemName,
|
||||
CmpRegistryMachineHardwareDescriptionSystemString );
|
||||
|
||||
RtlInitUnicodeString( &CmRegistryMachineHardwareDeviceMapName,
|
||||
CmpRegistryMachineHardwareDeviceMapString );
|
||||
|
||||
RtlInitUnicodeString( &CmRegistryMachineHardwareResourceMapName,
|
||||
CmpRegistryMachineHardwareResourceMapString );
|
||||
|
||||
RtlInitUnicodeString( &CmRegistryMachineHardwareOwnerMapName,
|
||||
CmpRegistryMachineHardwareOwnerMapString );
|
||||
|
||||
RtlInitUnicodeString( &CmRegistryMachineSystemName,
|
||||
CmpRegistryMachineSystemString );
|
||||
|
||||
RtlInitUnicodeString( &CmRegistryMachineSystemCurrentControlSet,
|
||||
CmpRegistryMachineSystemCurrentControlSetString);
|
||||
|
||||
RtlInitUnicodeString( &CmRegistryUserName,
|
||||
CmpRegistryUserString );
|
||||
|
||||
RtlInitUnicodeString( &CmRegistrySystemCloneName,
|
||||
CmpRegistrySystemCloneString );
|
||||
|
||||
RtlInitUnicodeString( &CmpSystemFileName,
|
||||
CmpRegistrySystemFileNameString );
|
||||
|
||||
RtlInitUnicodeString( &CmRegistryMachineSystemCurrentControlSetEnumName,
|
||||
CmpRegistryMachineSystemCurrentControlSetEnumString);
|
||||
|
||||
RtlInitUnicodeString( &CmRegistryMachineSystemCurrentControlSetEnumRootName,
|
||||
CmpRegistryMachineSystemCurrentControlSetEnumRootString);
|
||||
|
||||
RtlInitUnicodeString( &CmRegistryMachineSystemCurrentControlSetServices,
|
||||
CmpRegistryMachineSystemCurrentControlSetServicesString);
|
||||
|
||||
RtlInitUnicodeString( &CmRegistryMachineSystemCurrentControlSetHardwareProfilesCurrent,
|
||||
CmpRegistryMachineSystemCurrentControlSetHardwareProfilesCurrentString);
|
||||
|
||||
RtlInitUnicodeString( &CmRegistryMachineSystemCurrentControlSetControlClass,
|
||||
CmpRegistryMachineSystemCurrentControlSetControlClassString);
|
||||
|
||||
RtlInitUnicodeString( &CmRegistryMachineSystemCurrentControlSetControlSafeBoot,
|
||||
CmpRegistryMachineSystemCurrentControlSetControlSafeBootString);
|
||||
|
||||
RtlInitUnicodeString( &CmRegistryMachineSystemCurrentControlSetControlSessionManagerMemoryManagement,
|
||||
CmpRegistryMachineSystemCurrentControlSetControlSessionManagerMemoryManagementString);
|
||||
|
||||
RtlInitUnicodeString( &CmRegistryMachineSystemCurrentControlSetControlBootLog,
|
||||
CmpRegistryMachineSystemCurrentControlSetControlBootLogString);
|
||||
|
||||
RtlInitUnicodeString( &CmRegistryMachineSystemCurrentControlSetServicesEventLog,
|
||||
CmpRegistryMachineSystemCurrentControlSetServicesEventLogString);
|
||||
|
||||
RtlInitUnicodeString( &CmSymbolicLinkValueName,
|
||||
CmpSymbolicLinkValueName);
|
||||
|
||||
#ifdef _WANT_MACHINE_IDENTIFICATION
|
||||
RtlInitUnicodeString( &CmRegistryMachineSystemCurrentControlSetControlBiosInfo,
|
||||
CmpRegistryMachineSystemCurrentControlSetControlBiosInfoString);
|
||||
#endif
|
||||
|
||||
//
|
||||
// Initialize the type names for the hardware tree.
|
||||
//
|
||||
|
||||
for (i = 0; i <= MaximumType; i++) {
|
||||
|
||||
RtlInitUnicodeString( &(CmTypeName[i]),
|
||||
CmTypeString[i] );
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize the class names for the hardware tree.
|
||||
//
|
||||
|
||||
for (i = 0; i <= MaximumClass; i++) {
|
||||
|
||||
RtlInitUnicodeString( &(CmClassName[i]),
|
||||
CmClassString[i] );
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
855
base/ntos/config/cmdelay.c
Normal file
855
base/ntos/config/cmdelay.c
Normal file
@ -0,0 +1,855 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
cmdelay.c
|
||||
|
||||
Abstract:
|
||||
|
||||
This module implements the new algorithm (LRU style) for the
|
||||
Delayed Close KCB table.
|
||||
|
||||
Functions in this module are thread safe protected by the kcb lock.
|
||||
When kcb lock is converted to a resource, we should assert (enforce)
|
||||
exclusivity of that resource here !!!
|
||||
|
||||
Note:
|
||||
|
||||
We might want to convert these functions to macros after enough testing
|
||||
provides that they work well
|
||||
|
||||
--*/
|
||||
|
||||
#include "cmp.h"
|
||||
|
||||
ULONG CmpDelayedCloseSize = 2048; // !!!! Cannot be bigger that 4094 !!!!!
|
||||
ULONG CmpDelayedCloseElements = 0;
|
||||
|
||||
#define MAX_DELAY_WORKER_ITERATIONS ( CmpDelayedCloseSize / 4 )
|
||||
|
||||
VOID
|
||||
CmpDelayDerefKCBWorker(
|
||||
IN PVOID Parameter
|
||||
);
|
||||
|
||||
VOID
|
||||
CmpDelayCloseWorker(
|
||||
IN PVOID Parameter
|
||||
);
|
||||
|
||||
typedef struct _CM_DELAY_DEREF_KCB_ITEM {
|
||||
LIST_ENTRY ListEntry;
|
||||
PCM_KEY_CONTROL_BLOCK Kcb;
|
||||
} CM_DELAY_DEREF_KCB_ITEM, *PCM_DELAY_DEREF_KCB_ITEM;
|
||||
|
||||
VOID
|
||||
CmpDelayCloseDpcRoutine(
|
||||
IN PKDPC Dpc,
|
||||
IN PVOID DeferredContext,
|
||||
IN PVOID SystemArgument1,
|
||||
IN PVOID SystemArgument2
|
||||
);
|
||||
|
||||
VOID
|
||||
CmpDelayDerefKCBDpcRoutine(
|
||||
IN PKDPC Dpc,
|
||||
IN PVOID DeferredContext,
|
||||
IN PVOID SystemArgument1,
|
||||
IN PVOID SystemArgument2
|
||||
);
|
||||
|
||||
VOID
|
||||
CmpDoQueueLateUnloadWorker(IN PCMHIVE CmHive);
|
||||
|
||||
VOID
|
||||
CmpArmDelayedCloseTimer(VOID);
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE,CmpInitializeDelayedCloseTable)
|
||||
#pragma alloc_text(PAGE,CmpRemoveFromDelayedClose)
|
||||
#pragma alloc_text(PAGE,CmpAddToDelayedClose)
|
||||
|
||||
#pragma alloc_text(PAGE,CmpInitDelayDerefKCBEngine)
|
||||
#pragma alloc_text(PAGE,CmpRunDownDelayDerefKCBEngine)
|
||||
#pragma alloc_text(PAGE,CmpDelayDerefKeyControlBlock)
|
||||
#pragma alloc_text(PAGE,CmpDelayDerefKCBWorker)
|
||||
#pragma alloc_text(PAGE,CmpArmDelayedCloseTimer)
|
||||
#endif
|
||||
|
||||
WORK_QUEUE_ITEM CmpDelayCloseWorkItem;
|
||||
BOOLEAN CmpDelayCloseWorkItemActive = FALSE;
|
||||
|
||||
KGUARDED_MUTEX CmpDelayedCloseTableLock;
|
||||
LIST_ENTRY CmpDelayedLRUListHead; // head of the LRU list of Delayed Close Table entries
|
||||
|
||||
KTIMER CmpDelayCloseTimer;
|
||||
KDPC CmpDelayCloseDpc;
|
||||
|
||||
ULONG CmpDelayCloseIntervalInSeconds = 5;
|
||||
|
||||
|
||||
#define LOCK_DELAY_CLOSE() KeAcquireGuardedMutex(&CmpDelayedCloseTableLock)
|
||||
#define UNLOCK_DELAY_CLOSE() KeReleaseGuardedMutex(&CmpDelayedCloseTableLock)
|
||||
|
||||
VOID
|
||||
CmpDelayCloseDpcRoutine(
|
||||
IN PKDPC Dpc,
|
||||
IN PVOID DeferredContext,
|
||||
IN PVOID SystemArgument1,
|
||||
IN PVOID SystemArgument2
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This is the DPC routine triggered by the delayclose timer.
|
||||
is queue a work item to an executive worker thread.
|
||||
|
||||
Arguments:
|
||||
|
||||
Dpc - Supplies a pointer to the DPC object.
|
||||
|
||||
DeferredContext - not used
|
||||
|
||||
SystemArgument1 - not used
|
||||
|
||||
SystemArgument2 - not used
|
||||
|
||||
Return Value:
|
||||
|
||||
None.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
UNREFERENCED_PARAMETER (Dpc);
|
||||
UNREFERENCED_PARAMETER (DeferredContext);
|
||||
UNREFERENCED_PARAMETER (SystemArgument1);
|
||||
UNREFERENCED_PARAMETER (SystemArgument2);
|
||||
|
||||
ASSERT(CmpDelayCloseWorkItemActive);
|
||||
ExQueueWorkItem(&CmpDelayCloseWorkItem, DelayedWorkQueue);
|
||||
}
|
||||
|
||||
|
||||
#define CmpDelayCloseAllocNewEntry() (PCM_DELAYED_CLOSE_ENTRY)CmpAllocateDelayItem()
|
||||
#define CmpDelayCloseFreeEntry(Item) CmpFreeDelayItem((PVOID)(Item))
|
||||
|
||||
VOID
|
||||
CmpInitializeDelayedCloseTable()
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Initialize delayed close table; allocation + LRU list initialization.
|
||||
|
||||
Arguments:
|
||||
|
||||
|
||||
Return Value:
|
||||
|
||||
NONE.
|
||||
|
||||
--*/
|
||||
{
|
||||
ExInitializeWorkItem(&CmpDelayCloseWorkItem, CmpDelayCloseWorker, NULL);
|
||||
KeInitializeGuardedMutex(&CmpDelayedCloseTableLock);
|
||||
InitializeListHead(&(CmpDelayedLRUListHead));
|
||||
KeInitializeDpc(&CmpDelayCloseDpc,
|
||||
CmpDelayCloseDpcRoutine,
|
||||
NULL);
|
||||
|
||||
KeInitializeTimer(&CmpDelayCloseTimer);
|
||||
|
||||
}
|
||||
|
||||
VOID
|
||||
CmpDelayCloseWorker(
|
||||
IN PVOID Parameter
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
The fun part. We need to walk the cache and look for kcbs with refcount == 0
|
||||
Get the oldest one and kick it out of cache.
|
||||
|
||||
Arguments:
|
||||
|
||||
Parameter - not used.
|
||||
|
||||
Return Value:
|
||||
|
||||
None.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
PCM_DELAYED_CLOSE_ENTRY DelayedEntry;
|
||||
ULONG ConvKey;
|
||||
ULONG MaxIterations = MAX_DELAY_WORKER_ITERATIONS;
|
||||
|
||||
CM_PAGED_CODE();
|
||||
|
||||
UNREFERENCED_PARAMETER (Parameter);
|
||||
|
||||
ASSERT(CmpDelayCloseWorkItemActive);
|
||||
|
||||
BEGIN_LOCK_CHECKPOINT;
|
||||
CmpLockRegistry();
|
||||
|
||||
//
|
||||
// process kick out every entry with RefCount == 0 && DelayCloseIndex == 0
|
||||
// ignore the others; we only do this while there is excess of delay - close kcbs
|
||||
//
|
||||
LOCK_DELAY_CLOSE();
|
||||
while( (CmpDelayedCloseElements > CmpDelayedCloseSize) && (MaxIterations--) ) {
|
||||
ASSERT( !CmpIsListEmpty(&CmpDelayedLRUListHead) );
|
||||
//
|
||||
// We first need to get the hash entry and attempt to lock it.
|
||||
//
|
||||
DelayedEntry = (PCM_DELAYED_CLOSE_ENTRY)(CmpDelayedLRUListHead.Blink);
|
||||
DelayedEntry = CONTAINING_RECORD( DelayedEntry,
|
||||
CM_DELAYED_CLOSE_ENTRY,
|
||||
DelayedLRUList);
|
||||
ConvKey = DelayedEntry->KeyControlBlock->ConvKey;
|
||||
UNLOCK_DELAY_CLOSE();
|
||||
//
|
||||
// now lock the hash then recheck if the entry is still first on the list
|
||||
//
|
||||
CmpLockHashEntryExclusive(ConvKey);
|
||||
LOCK_DELAY_CLOSE();
|
||||
if( CmpDelayedCloseElements <= CmpDelayedCloseSize ) {
|
||||
//
|
||||
// just bail out; no need to kick them out
|
||||
//
|
||||
CmpUnlockHashEntry(ConvKey);
|
||||
break;
|
||||
}
|
||||
DelayedEntry = (PCM_DELAYED_CLOSE_ENTRY)(CmpDelayedLRUListHead.Blink);
|
||||
DelayedEntry = CONTAINING_RECORD( DelayedEntry,
|
||||
CM_DELAYED_CLOSE_ENTRY,
|
||||
DelayedLRUList);
|
||||
if( ConvKey == DelayedEntry->KeyControlBlock->ConvKey ) {
|
||||
//
|
||||
// same hash entry; proceed
|
||||
// pull it out of the list
|
||||
//
|
||||
DelayedEntry = (PCM_DELAYED_CLOSE_ENTRY)RemoveTailList(&CmpDelayedLRUListHead);
|
||||
|
||||
DelayedEntry = CONTAINING_RECORD( DelayedEntry,
|
||||
CM_DELAYED_CLOSE_ENTRY,
|
||||
DelayedLRUList);
|
||||
CmpClearListEntry(&(DelayedEntry->DelayedLRUList));
|
||||
|
||||
if( (DelayedEntry->KeyControlBlock->RefCount == 0) && (DelayedEntry->KeyControlBlock->DelayedCloseIndex == 0) ){
|
||||
//
|
||||
// free this kcb and the entry
|
||||
//
|
||||
UNLOCK_DELAY_CLOSE();
|
||||
DelayedEntry->KeyControlBlock->DelayCloseEntry = NULL;
|
||||
CmpCleanUpKcbCacheWithLock(DelayedEntry->KeyControlBlock,FALSE);
|
||||
CmpDelayCloseFreeEntry(DelayedEntry);
|
||||
InterlockedDecrement((PLONG)&CmpDelayedCloseElements);
|
||||
} else {
|
||||
//
|
||||
// put it back at the top
|
||||
//
|
||||
InsertHeadList( &CmpDelayedLRUListHead,
|
||||
&(DelayedEntry->DelayedLRUList)
|
||||
);
|
||||
UNLOCK_DELAY_CLOSE();
|
||||
}
|
||||
} else {
|
||||
UNLOCK_DELAY_CLOSE();
|
||||
}
|
||||
CmpUnlockHashEntry(ConvKey);
|
||||
|
||||
LOCK_DELAY_CLOSE();
|
||||
}
|
||||
if( CmpDelayedCloseElements > CmpDelayedCloseSize ) {
|
||||
//
|
||||
// iteration run was too short, there are more elements to process, queue ourselves for later
|
||||
//
|
||||
CmpArmDelayedCloseTimer();
|
||||
} else {
|
||||
//
|
||||
// signal that we have finished our work.
|
||||
//
|
||||
CmpDelayCloseWorkItemActive = FALSE;
|
||||
}
|
||||
UNLOCK_DELAY_CLOSE();
|
||||
|
||||
|
||||
CmpUnlockRegistry();
|
||||
END_LOCK_CHECKPOINT;
|
||||
}
|
||||
|
||||
VOID
|
||||
CmpArmDelayedCloseTimer( )
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Arms timer for DelayClose worker procession
|
||||
|
||||
NB: this routine should be called with CmpDelayedCloseTableLock held.
|
||||
If not --> change CmpDelayCloseWorkItemActive to a ULONG and do an InterlockedCompareExchange on it
|
||||
before setting the timer
|
||||
|
||||
Arguments:
|
||||
|
||||
|
||||
Note:
|
||||
|
||||
|
||||
Return Value:
|
||||
|
||||
NONE.
|
||||
|
||||
--*/
|
||||
{
|
||||
LARGE_INTEGER DueTime;
|
||||
|
||||
CM_PAGED_CODE();
|
||||
|
||||
CmpDelayCloseWorkItemActive = TRUE;
|
||||
|
||||
//
|
||||
// queue a timer for 5 secs later to do the actual delay close
|
||||
//
|
||||
|
||||
DueTime.QuadPart = Int32x32To64(CmpDelayCloseIntervalInSeconds,
|
||||
- SECOND_MULT);
|
||||
//
|
||||
// Indicate relative time
|
||||
//
|
||||
|
||||
KeSetTimer(&CmpDelayCloseTimer,
|
||||
DueTime,
|
||||
&CmpDelayCloseDpc);
|
||||
|
||||
}
|
||||
|
||||
VOID
|
||||
CmpRemoveFromDelayedClose(
|
||||
IN PCM_KEY_CONTROL_BLOCK kcb
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Removes a KCB from the delayed close table;
|
||||
|
||||
Arguments:
|
||||
|
||||
kcb - the kcb in question
|
||||
|
||||
Note:
|
||||
|
||||
kcb lock/resource should be acquired exclusively when this function is called
|
||||
|
||||
Return Value:
|
||||
|
||||
NONE.
|
||||
|
||||
--*/
|
||||
{
|
||||
PCM_DELAYED_CLOSE_ENTRY DelayedEntry;
|
||||
|
||||
CM_PAGED_CODE();
|
||||
|
||||
|
||||
ASSERT( (CmpIsKCBLockedExclusive(kcb) == TRUE) || // this kcb is owned exclusive
|
||||
(CmpTestRegistryLockExclusive() == TRUE) ); // or the entire registry is locked exclusive
|
||||
|
||||
// not on delay close; don't try to remove it.
|
||||
if (kcb->DelayedCloseIndex == CmpDelayedCloseSize) { // see if we really need this
|
||||
ASSERT( FALSE );
|
||||
return;
|
||||
}
|
||||
|
||||
DelayedEntry = (PCM_DELAYED_CLOSE_ENTRY)kcb->DelayCloseEntry;
|
||||
if( DelayedEntry != NULL ) {
|
||||
LOCK_DELAY_CLOSE();
|
||||
CmpRemoveEntryList(&(DelayedEntry->DelayedLRUList));
|
||||
UNLOCK_DELAY_CLOSE();
|
||||
|
||||
//
|
||||
// give back the entry
|
||||
//
|
||||
CmpDelayCloseFreeEntry(DelayedEntry);
|
||||
InterlockedDecrement((PLONG)&CmpDelayedCloseElements);
|
||||
#if DBG
|
||||
if( kcb->InDelayClose == 0 ) {
|
||||
ASSERT( FALSE );
|
||||
}
|
||||
{
|
||||
LONG OldRefCount;
|
||||
LONG NewRefCount;
|
||||
|
||||
OldRefCount = *(PLONG)&kcb->InDelayClose; //get entire dword
|
||||
ASSERT( OldRefCount == 1 );
|
||||
NewRefCount = 0;
|
||||
if( InterlockedCompareExchange((PLONG)&kcb->InDelayClose,NewRefCount,OldRefCount)
|
||||
!= OldRefCount ) {
|
||||
|
||||
ASSERT( FALSE );
|
||||
}
|
||||
}
|
||||
#endif //DBG
|
||||
}
|
||||
|
||||
//
|
||||
// easy enough huh ?
|
||||
//
|
||||
kcb->DelayedCloseIndex = CmpDelayedCloseSize; // see if we really need this
|
||||
kcb->DelayCloseEntry = NULL;
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
CmpAddToDelayedClose(
|
||||
IN PCM_KEY_CONTROL_BLOCK kcb,
|
||||
IN BOOLEAN RegLockHeldEx
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Adds a kcb to the delayed close table
|
||||
|
||||
Arguments:
|
||||
|
||||
kcb - the kcb in question
|
||||
|
||||
Note:
|
||||
|
||||
kcb lock/resource should be acquired exclusively when this function is called
|
||||
|
||||
Return Value:
|
||||
|
||||
NONE.
|
||||
|
||||
--*/
|
||||
{
|
||||
PCM_DELAYED_CLOSE_ENTRY DelayedEntry = NULL;
|
||||
|
||||
CM_PAGED_CODE();
|
||||
|
||||
ASSERT( (CmpIsKCBLockedExclusive(kcb) == TRUE) || // this kcb is owned exclusive
|
||||
(CmpTestRegistryLockExclusive() == TRUE) ); // or the entire registry is locked exclusive
|
||||
|
||||
|
||||
// Already on delayed close, don't try to put on again
|
||||
if (kcb->DelayedCloseIndex != CmpDelayedCloseSize) { // see if we really need this
|
||||
ASSERT( FALSE );
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT(kcb->RefCount == 0);
|
||||
|
||||
//
|
||||
// now materialize a new entry for this kcb
|
||||
//
|
||||
ASSERT_KEYBODY_LIST_EMPTY(kcb);
|
||||
DelayedEntry = CmpDelayCloseAllocNewEntry();
|
||||
if( !DelayedEntry ) {
|
||||
//
|
||||
// this is bad luck; we need to free the kcb in place
|
||||
//
|
||||
CmpCleanUpKcbCacheWithLock(kcb,RegLockHeldEx);
|
||||
return;
|
||||
}
|
||||
#if DBG
|
||||
if( kcb->InDelayClose != 0 ) {
|
||||
ASSERT( FALSE );
|
||||
}
|
||||
{
|
||||
LONG OldRefCount;
|
||||
LONG NewRefCount;
|
||||
|
||||
OldRefCount = *(PLONG)&kcb->InDelayClose; //get entire dword
|
||||
ASSERT( OldRefCount == 0 );
|
||||
NewRefCount = 1;
|
||||
if( InterlockedCompareExchange((PLONG)&kcb->InDelayClose,NewRefCount,OldRefCount)
|
||||
!= OldRefCount ) {
|
||||
|
||||
ASSERT( FALSE );
|
||||
}
|
||||
}
|
||||
#endif //DBG
|
||||
//
|
||||
// populate the entry and insert it into the LRU list (at the top).
|
||||
//
|
||||
kcb->DelayedCloseIndex = 0; // see if we really need this
|
||||
kcb->DelayCloseEntry = (PVOID)DelayedEntry; // need this for removing it back from here
|
||||
DelayedEntry->KeyControlBlock = kcb;
|
||||
InterlockedIncrement((PLONG)&CmpDelayedCloseElements);
|
||||
|
||||
LOCK_DELAY_CLOSE();
|
||||
InsertHeadList(
|
||||
&CmpDelayedLRUListHead,
|
||||
&(DelayedEntry->DelayedLRUList)
|
||||
);
|
||||
//
|
||||
// check if limit hit and arm timer if not already armed
|
||||
//
|
||||
if( (CmpDelayedCloseElements > CmpDelayedCloseSize) && (!CmpDelayCloseWorkItemActive) ) {
|
||||
CmpArmDelayedCloseTimer();
|
||||
}
|
||||
UNLOCK_DELAY_CLOSE();
|
||||
//
|
||||
// we're done here
|
||||
//
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------//
|
||||
// //
|
||||
// Delayed KCB deref. Used when we hit a symlink or when we simply cannot safely acquire the kcb lock //
|
||||
// //
|
||||
//-----------------------------------------------------------------------------------------------------------//
|
||||
LIST_ENTRY CmpDelayDerefKCBListHead;
|
||||
KGUARDED_MUTEX CmpDelayDerefKCBLock;
|
||||
WORK_QUEUE_ITEM CmpDelayDerefKCBWorkItem;
|
||||
BOOLEAN CmpDelayDerefKCBWorkItemActive = FALSE;
|
||||
|
||||
KTIMER CmpDelayDerefKCBTimer;
|
||||
KDPC CmpDelayDerefKCBDpc;
|
||||
|
||||
ULONG CmpDelayDerefKCBIntervalInSeconds = 5;
|
||||
|
||||
|
||||
#define LOCK_KCB_DELAY_DEREF_LIST() KeAcquireGuardedMutex(&CmpDelayDerefKCBLock)
|
||||
#define UNLOCK_KCB_DELAY_DEREF_LIST() KeReleaseGuardedMutex(&CmpDelayDerefKCBLock)
|
||||
|
||||
VOID
|
||||
CmpDelayDerefKCBDpcRoutine(
|
||||
IN PKDPC Dpc,
|
||||
IN PVOID DeferredContext,
|
||||
IN PVOID SystemArgument1,
|
||||
IN PVOID SystemArgument2
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This is the DPC routine triggered by the delayclose timer.
|
||||
is queue a work item to an executive worker thread.
|
||||
|
||||
Arguments:
|
||||
|
||||
Dpc - Supplies a pointer to the DPC object.
|
||||
|
||||
DeferredContext - not used
|
||||
|
||||
SystemArgument1 - not used
|
||||
|
||||
SystemArgument2 - not used
|
||||
|
||||
Return Value:
|
||||
|
||||
None.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
UNREFERENCED_PARAMETER (Dpc);
|
||||
UNREFERENCED_PARAMETER (DeferredContext);
|
||||
UNREFERENCED_PARAMETER (SystemArgument1);
|
||||
UNREFERENCED_PARAMETER (SystemArgument2);
|
||||
|
||||
ASSERT(CmpDelayDerefKCBWorkItemActive);
|
||||
ExQueueWorkItem(&CmpDelayDerefKCBWorkItem, DelayedWorkQueue);
|
||||
}
|
||||
|
||||
#define CmpDelayDerefKCBAllocNewEntry() (PCM_DELAY_DEREF_KCB_ITEM)CmpAllocateDelayItem()
|
||||
#define CmpDelayDerefKCBFreeEntry(Item) CmpFreeDelayItem((PVOID)(Item))
|
||||
|
||||
//#define CmpDelayDerefKCBAllocNewEntry() (PCM_DELAY_DEREF_KCB_ITEM)ExAllocatePool(PagedPool,sizeof(CM_DELAY_DEREF_KCB_ITEM))
|
||||
//#define CmpDelayDerefKCBFreeEntry(Item) ExFreePool(Item)
|
||||
|
||||
|
||||
VOID
|
||||
CmpInitDelayDerefKCBEngine()
|
||||
{
|
||||
InitializeListHead(&CmpDelayDerefKCBListHead);
|
||||
KeInitializeGuardedMutex(&CmpDelayDerefKCBLock);
|
||||
ExInitializeWorkItem(&CmpDelayDerefKCBWorkItem, CmpDelayDerefKCBWorker, NULL);
|
||||
|
||||
KeInitializeDpc(&CmpDelayDerefKCBDpc,
|
||||
CmpDelayDerefKCBDpcRoutine,
|
||||
NULL);
|
||||
|
||||
KeInitializeTimer(&CmpDelayDerefKCBTimer);
|
||||
}
|
||||
|
||||
VOID
|
||||
CmpRunDownDelayDerefKCBEngine( PCM_KEY_CONTROL_BLOCK KeyControlBlock,
|
||||
BOOLEAN RegLockHeldEx)
|
||||
{
|
||||
PCM_DELAY_DEREF_KCB_ITEM DelayItem;
|
||||
ULONG NewIndex;
|
||||
ULONG Index1 = CmpHashTableSize;
|
||||
ULONG Index2 = CmpHashTableSize;
|
||||
PCMHIVE CmHive = NULL;
|
||||
BOOLEAN DoUnloadCheck = FALSE;
|
||||
|
||||
CM_PAGED_CODE();
|
||||
|
||||
ASSERT_CM_LOCK_OWNED();
|
||||
|
||||
ASSERT( (KeyControlBlock && CmpIsKCBLockedExclusive(KeyControlBlock)) || (CmpTestRegistryLockExclusive() == TRUE) );
|
||||
|
||||
if( KeyControlBlock ) {
|
||||
Index1 = GET_HASH_INDEX(KeyControlBlock->ConvKey);
|
||||
if( KeyControlBlock->ParentKcb ) {
|
||||
Index2 = GET_HASH_INDEX(KeyControlBlock->ParentKcb->ConvKey);
|
||||
}
|
||||
}
|
||||
LOCK_KCB_DELAY_DEREF_LIST();
|
||||
while( !CmpIsListEmpty(&CmpDelayDerefKCBListHead) ) {
|
||||
//
|
||||
// pull it out of the list
|
||||
//
|
||||
DelayItem = (PCM_DELAY_DEREF_KCB_ITEM)RemoveHeadList(&CmpDelayDerefKCBListHead);
|
||||
UNLOCK_KCB_DELAY_DEREF_LIST();
|
||||
|
||||
DelayItem = CONTAINING_RECORD( DelayItem,
|
||||
CM_DELAY_DEREF_KCB_ITEM,
|
||||
ListEntry);
|
||||
CmpClearListEntry(&(DelayItem->ListEntry));
|
||||
|
||||
//
|
||||
// take additional precaution in the case the hive has been unloaded and this is the root
|
||||
//
|
||||
DoUnloadCheck = FALSE;
|
||||
if( !DelayItem->Kcb->Delete ) {
|
||||
CmHive = (PCMHIVE)CONTAINING_RECORD(DelayItem->Kcb->KeyHive, CMHIVE, Hive);
|
||||
if( IsHiveFrozen(CmHive) ) {
|
||||
//
|
||||
// unload is pending for this hive;
|
||||
//
|
||||
DoUnloadCheck = TRUE;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
NewIndex = GET_HASH_INDEX(DelayItem->Kcb->ConvKey);
|
||||
//
|
||||
// now deref and free
|
||||
//
|
||||
if( (NewIndex == Index1) || (NewIndex == Index2) ) {
|
||||
//
|
||||
// we already hold the lock
|
||||
//
|
||||
ASSERT_KCB_LOCKED_EXCLUSIVE(DelayItem->Kcb);
|
||||
CmpDereferenceKeyControlBlockWithLock(DelayItem->Kcb,RegLockHeldEx);
|
||||
} else {
|
||||
//
|
||||
// we can't afford to force acquire; try to acquire and if it fails bail out
|
||||
//
|
||||
if( CmpKCBLockForceAcquireAllowed(Index1,Index2,NewIndex) ) {
|
||||
CmpLockHashEntryByIndexExclusive(NewIndex);
|
||||
} else if( CmpTryToLockHashEntryByIndexExclusive(NewIndex) == FALSE ) {
|
||||
//
|
||||
// add the item back to the list and bail out
|
||||
//
|
||||
ASSERT( CmpTestRegistryLockExclusive() == FALSE );
|
||||
LOCK_KCB_DELAY_DEREF_LIST();
|
||||
InsertHeadList(&CmpDelayDerefKCBListHead,&(DelayItem->ListEntry));
|
||||
UNLOCK_KCB_DELAY_DEREF_LIST();
|
||||
return;
|
||||
}
|
||||
ASSERT_KCB_LOCKED_EXCLUSIVE(DelayItem->Kcb);
|
||||
CmpDereferenceKeyControlBlockWithLock(DelayItem->Kcb,RegLockHeldEx);
|
||||
CmpUnlockHashEntryByIndex(NewIndex);
|
||||
}
|
||||
CmpDelayDerefKCBFreeEntry(DelayItem);
|
||||
|
||||
//
|
||||
// if we dropped a reference inside a frozen hive, we may need to unload the hive
|
||||
//
|
||||
if( DoUnloadCheck == TRUE ) {
|
||||
CmpDoQueueLateUnloadWorker(CmHive);
|
||||
}
|
||||
|
||||
LOCK_KCB_DELAY_DEREF_LIST();
|
||||
}
|
||||
UNLOCK_KCB_DELAY_DEREF_LIST();
|
||||
}
|
||||
|
||||
VOID
|
||||
CmpDelayDerefKCBWorker(
|
||||
IN PVOID Parameter
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
|
||||
Arguments:
|
||||
|
||||
Parameter - not used.
|
||||
|
||||
Return Value:
|
||||
|
||||
None.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
PCM_DELAY_DEREF_KCB_ITEM DelayItem;
|
||||
PCMHIVE CmHive = NULL;
|
||||
BOOLEAN DoUnloadCheck = FALSE;
|
||||
|
||||
CM_PAGED_CODE();
|
||||
|
||||
UNREFERENCED_PARAMETER (Parameter);
|
||||
|
||||
ASSERT(CmpDelayDerefKCBWorkItemActive);
|
||||
|
||||
BEGIN_LOCK_CHECKPOINT;
|
||||
CmpLockRegistry();
|
||||
|
||||
LOCK_KCB_DELAY_DEREF_LIST();
|
||||
while( !CmpIsListEmpty(&CmpDelayDerefKCBListHead) ) {
|
||||
//
|
||||
// pull it out of the list
|
||||
//
|
||||
DelayItem = (PCM_DELAY_DEREF_KCB_ITEM)RemoveHeadList(&CmpDelayDerefKCBListHead);
|
||||
UNLOCK_KCB_DELAY_DEREF_LIST();
|
||||
|
||||
DelayItem = CONTAINING_RECORD( DelayItem,
|
||||
CM_DELAY_DEREF_KCB_ITEM,
|
||||
ListEntry);
|
||||
CmpClearListEntry(&(DelayItem->ListEntry));
|
||||
//
|
||||
// take additional precaution in the case the hive has been unloaded and this is the root
|
||||
//
|
||||
DoUnloadCheck = FALSE;
|
||||
if( !DelayItem->Kcb->Delete ) {
|
||||
CmHive = (PCMHIVE)CONTAINING_RECORD(DelayItem->Kcb->KeyHive, CMHIVE, Hive);
|
||||
if( IsHiveFrozen(CmHive) ) {
|
||||
//
|
||||
// unload is pending for this hive;
|
||||
//
|
||||
DoUnloadCheck = TRUE;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// now deref and free
|
||||
//
|
||||
CmpDereferenceKeyControlBlock(DelayItem->Kcb);
|
||||
CmpDelayDerefKCBFreeEntry(DelayItem);
|
||||
|
||||
//
|
||||
// if we dropped a reference inside a frozen hive, we may need to unload the hive
|
||||
//
|
||||
if( DoUnloadCheck == TRUE ) {
|
||||
CmpDoQueueLateUnloadWorker(CmHive);
|
||||
}
|
||||
|
||||
LOCK_KCB_DELAY_DEREF_LIST();
|
||||
}
|
||||
//
|
||||
// signal that we have finished our work.
|
||||
//
|
||||
CmpDelayDerefKCBWorkItemActive = FALSE;
|
||||
UNLOCK_KCB_DELAY_DEREF_LIST();
|
||||
|
||||
CmpUnlockRegistry();
|
||||
END_LOCK_CHECKPOINT;
|
||||
}
|
||||
|
||||
VOID
|
||||
CmpDelayDerefKeyControlBlock( PCM_KEY_CONTROL_BLOCK KeyControlBlock )
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Adds kcb to a list to be deref in a workitem
|
||||
|
||||
Arguments:
|
||||
|
||||
kcb - the kcb in question
|
||||
|
||||
Note:
|
||||
|
||||
kcb lock/resource should be acquired exclusively when this function is called
|
||||
|
||||
Return Value:
|
||||
|
||||
NONE.
|
||||
|
||||
--*/
|
||||
{
|
||||
PCM_DELAY_DEREF_KCB_ITEM DelayItem;
|
||||
LONG OldRefCount;
|
||||
LONG NewRefCount;
|
||||
|
||||
CM_PAGED_CODE();
|
||||
|
||||
//
|
||||
// try the fast path first; we only need to take the work item approach when we drop to 0
|
||||
//
|
||||
OldRefCount = *(PLONG)&KeyControlBlock->RefCount; //get entire dword
|
||||
NewRefCount = OldRefCount - 1;
|
||||
if( (NewRefCount & 0xffff) > 0 &&
|
||||
InterlockedCompareExchange((PLONG)&KeyControlBlock->RefCount,NewRefCount,OldRefCount)
|
||||
== OldRefCount ) {
|
||||
|
||||
LogKCBReference(KeyControlBlock,2);
|
||||
return;
|
||||
}
|
||||
|
||||
DelayItem = CmpDelayDerefKCBAllocNewEntry();
|
||||
if( DelayItem == NULL ) {
|
||||
//
|
||||
// nothing to do here ; we'll leak a reference on this kcb
|
||||
//
|
||||
return;
|
||||
}
|
||||
|
||||
DelayItem->Kcb = KeyControlBlock;
|
||||
LOCK_KCB_DELAY_DEREF_LIST();
|
||||
InsertTailList( &CmpDelayDerefKCBListHead,&(DelayItem->ListEntry));
|
||||
//
|
||||
// if worker is not already up; queue it
|
||||
//
|
||||
if( !CmpDelayDerefKCBWorkItemActive ) {
|
||||
LARGE_INTEGER DueTime;
|
||||
|
||||
CmpDelayDerefKCBWorkItemActive = TRUE;
|
||||
|
||||
//
|
||||
// queue a timer for 5 secs later to do the actual delay close
|
||||
//
|
||||
|
||||
DueTime.QuadPart = Int32x32To64(CmpDelayDerefKCBIntervalInSeconds,
|
||||
- SECOND_MULT);
|
||||
//
|
||||
// Indicate relative time
|
||||
//
|
||||
|
||||
KeSetTimer(&CmpDelayDerefKCBTimer,
|
||||
DueTime,
|
||||
&CmpDelayDerefKCBDpc);
|
||||
}
|
||||
UNLOCK_KCB_DELAY_DEREF_LIST();
|
||||
}
|
||||
|
||||
320
base/ntos/config/cmdelete.c
Normal file
320
base/ntos/config/cmdelete.c
Normal file
@ -0,0 +1,320 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
cmdelete.c
|
||||
|
||||
Abstract:
|
||||
|
||||
This module contains the delete object method (used to delete key
|
||||
control blocks when last handle to a key is closed, and to delete
|
||||
keys marked for deletetion when last reference to them goes away.)
|
||||
|
||||
--*/
|
||||
|
||||
#include "cmp.h"
|
||||
|
||||
extern BOOLEAN HvShutdownComplete;
|
||||
|
||||
VOID
|
||||
CmpLateUnloadHiveWorker(
|
||||
IN PVOID Hive
|
||||
);
|
||||
VOID
|
||||
CmpDoQueueLateUnloadWorker(IN PCMHIVE CmHive);
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE,CmpDeleteKeyObject)
|
||||
#pragma alloc_text(PAGE,CmpLateUnloadHiveWorker)
|
||||
#pragma alloc_text(PAGE,CmpDoQueueLateUnloadWorker)
|
||||
#endif
|
||||
|
||||
|
||||
VOID
|
||||
CmpDeleteKeyObject(
|
||||
IN PVOID Object
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine interfaces to the NT Object Manager. It is invoked when
|
||||
the last reference to a particular Key object (or Key Root object)
|
||||
is destroyed.
|
||||
|
||||
If the Key object going away holds the last reference to
|
||||
the extension it is associated with, that extension is destroyed.
|
||||
|
||||
Arguments:
|
||||
|
||||
Object - supplies a pointer to a KeyRoot or Key, thus -> KEY_BODY.
|
||||
|
||||
Return Value:
|
||||
|
||||
NONE.
|
||||
|
||||
--*/
|
||||
{
|
||||
PCM_KEY_CONTROL_BLOCK KeyControlBlock;
|
||||
PCM_KEY_BODY KeyBody;
|
||||
PCMHIVE CmHive = NULL;
|
||||
BOOLEAN DoUnloadCheck = FALSE;
|
||||
|
||||
CM_PAGED_CODE();
|
||||
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_FLOW,"CmpDeleteKeyObject: Object = %p\n", Object));
|
||||
|
||||
//
|
||||
// HandleClose callback
|
||||
//
|
||||
if ( CmAreCallbacksRegistered() ) {
|
||||
REG_KEY_HANDLE_CLOSE_INFORMATION KeyHandleCloseInfo;
|
||||
|
||||
KeyHandleCloseInfo.Object = Object;
|
||||
|
||||
CmpCallCallBacks(RegNtPreKeyHandleClose,&KeyHandleCloseInfo,TRUE,RegNtPostKeyHandleClose,Object);
|
||||
}
|
||||
|
||||
KeyBody = (PCM_KEY_BODY)Object;
|
||||
|
||||
BEGIN_LOCK_CHECKPOINT;
|
||||
|
||||
CmpLockRegistry();
|
||||
|
||||
if (KeyBody->Type==KEY_BODY_TYPE) {
|
||||
KeyControlBlock = KeyBody->KeyControlBlock;
|
||||
|
||||
//
|
||||
// the keybody should be initialized; when kcb is null, something went wrong
|
||||
// between the creation and the dereferenciation of the object
|
||||
//
|
||||
if( KeyControlBlock != NULL ) {
|
||||
//
|
||||
// Clean up any outstanding notifies attached to the KeyBody
|
||||
//
|
||||
CmpFlushNotify(KeyBody,FALSE);
|
||||
|
||||
//
|
||||
// Remove our reference to the KeyControlBlock, clean it up, perform any
|
||||
// pend-till-final-close operations.
|
||||
//
|
||||
// NOTE: Delete notification is seen at the parent of the deleted key,
|
||||
// not the deleted key itself. If any notify was outstanding on
|
||||
// this key, it was cleared away above us. Only parent/ancestor
|
||||
// keys will see the report.
|
||||
//
|
||||
//
|
||||
// The dereference will free the KeyControlBlock. If the key was deleted, it
|
||||
// has already been removed from the hash table, and relevant notifications
|
||||
// posted then as well. All we are doing is freeing the tombstone.
|
||||
//
|
||||
// If it was not deleted, we're both cutting the kcb out of
|
||||
// the kcb list/tree, AND freeing its storage.
|
||||
//
|
||||
|
||||
|
||||
//
|
||||
// Replace this with the definition so we avoid dropping and reacquiring the lock
|
||||
DelistKeyBodyFromKCB(KeyBody,FALSE);
|
||||
|
||||
//
|
||||
// take additional precaution in the case the hive has been unloaded and this is the root
|
||||
//
|
||||
if( !KeyControlBlock->Delete ) {
|
||||
CmHive = (PCMHIVE)CONTAINING_RECORD(KeyControlBlock->KeyHive, CMHIVE, Hive);
|
||||
if( IsHiveFrozen(CmHive) ) {
|
||||
//
|
||||
// unload is pending for this hive;
|
||||
//
|
||||
DoUnloadCheck = TRUE;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
CmpDelayDerefKeyControlBlock(KeyControlBlock);
|
||||
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// This must be a predefined handle
|
||||
// some sanity asserts
|
||||
//
|
||||
KeyControlBlock = KeyBody->KeyControlBlock;
|
||||
|
||||
ASSERT( KeyBody->Type®_PREDEF_HANDLE_MASK);
|
||||
ASSERT( KeyControlBlock->Flags&KEY_PREDEF_HANDLE );
|
||||
|
||||
if( KeyControlBlock != NULL ) {
|
||||
CmHive = (PCMHIVE)CONTAINING_RECORD(KeyControlBlock->KeyHive, CMHIVE, Hive);
|
||||
if( IsHiveFrozen(CmHive) ) {
|
||||
//
|
||||
// unload is pending for this hive; we shouldn't put the kcb in the delay
|
||||
// close table
|
||||
//
|
||||
DoUnloadCheck = TRUE;
|
||||
|
||||
}
|
||||
CmpDereferenceKeyControlBlock(KeyControlBlock);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// if a handle inside a frozen hive has been closed, we may need to unload the hive
|
||||
//
|
||||
if( DoUnloadCheck == TRUE ) {
|
||||
CmpDoQueueLateUnloadWorker(CmHive);
|
||||
}
|
||||
|
||||
CmpUnlockRegistry();
|
||||
END_LOCK_CHECKPOINT;
|
||||
|
||||
//
|
||||
// just a notification; disregard the return status
|
||||
//
|
||||
CmPostCallbackNotification(RegNtPostKeyHandleClose,NULL,STATUS_SUCCESS);
|
||||
return;
|
||||
}
|
||||
|
||||
VOID
|
||||
CmpDoQueueLateUnloadWorker(IN PCMHIVE CmHive)
|
||||
{
|
||||
PWORK_QUEUE_ITEM WorkItem;
|
||||
|
||||
CM_PAGED_CODE();
|
||||
|
||||
ASSERT( CmHive->RootKcb != NULL );
|
||||
|
||||
//
|
||||
// NB: Hive lock has higher precedence; We don't need the kcb lock as we are only checking the refcount
|
||||
//
|
||||
CmLockHive(CmHive);
|
||||
|
||||
if( (CmHive->RootKcb->RefCount == 1) && (CmHive->UnloadWorkItem == NULL) ) {
|
||||
//
|
||||
// the only reference on the rookcb is the one that we artificially created
|
||||
// queue a work item to late unload the hive
|
||||
//
|
||||
WorkItem = ExAllocatePool(NonPagedPool, sizeof(WORK_QUEUE_ITEM));
|
||||
if( InterlockedCompareExchangePointer(&(CmHive->UnloadWorkItem),WorkItem,NULL) == NULL ) {
|
||||
ExInitializeWorkItem(CmHive->UnloadWorkItem,
|
||||
CmpLateUnloadHiveWorker,
|
||||
CmHive);
|
||||
ExQueueWorkItem(CmHive->UnloadWorkItem, DelayedWorkQueue);
|
||||
} else {
|
||||
ExFreePool(WorkItem);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CmUnlockHive(CmHive);
|
||||
}
|
||||
|
||||
VOID
|
||||
CmpLateUnloadHiveWorker(
|
||||
IN PVOID Hive
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
"Late" unloads the hive; If nothing goes badly wrong (i.e. insufficient resources),
|
||||
this function should succeed
|
||||
|
||||
Arguments:
|
||||
|
||||
CmHive - the frozen hive to be unloaded
|
||||
|
||||
Return Value:
|
||||
|
||||
NONE.
|
||||
|
||||
--*/
|
||||
{
|
||||
NTSTATUS Status;
|
||||
HCELL_INDEX Cell;
|
||||
PCM_KEY_CONTROL_BLOCK RootKcb;
|
||||
PCMHIVE CmHive;
|
||||
|
||||
CM_PAGED_CODE();
|
||||
|
||||
//
|
||||
// first, load the registry exclusive
|
||||
//
|
||||
CmpLockRegistryExclusive();
|
||||
|
||||
//
|
||||
// hive is the parameter to this worker; make sure we free the work item
|
||||
// allocated by CmpDeleteKeyObject
|
||||
//
|
||||
CmHive = (PCMHIVE)Hive;
|
||||
|
||||
ASSERT( CmHive->UnloadWorkItem != NULL );
|
||||
ExFreePool( CmHive->UnloadWorkItem );
|
||||
|
||||
//
|
||||
// if this attempt doesn't succeed, mark that we can try another
|
||||
//
|
||||
CmHive->UnloadWorkItem = NULL;
|
||||
|
||||
ASSERT( !(CmHive->Hive.HiveFlags & HIVE_IS_UNLOADING) );
|
||||
if( CmHive->Frozen == FALSE ) {
|
||||
//
|
||||
// another thread mounted the exact same hive in the exact same place, hence unfreezing the hive
|
||||
// we've done the cleanup part (free the workitem) nothing more to do.
|
||||
// or hive is already in process of being unloaded
|
||||
//
|
||||
ASSERT( CmHive->RootKcb == NULL );
|
||||
CmpUnlockRegistry();
|
||||
return;
|
||||
}
|
||||
//
|
||||
// this is just about the only possible way the hive can get corrupted in between
|
||||
//
|
||||
if( HvShutdownComplete == TRUE ) {
|
||||
// too late to do anything
|
||||
CmpUnlockRegistry();
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// hive should be frozen, otherwise we wouldn't get here
|
||||
//
|
||||
ASSERT( CmHive->Frozen == TRUE );
|
||||
|
||||
RootKcb = CmHive->RootKcb;
|
||||
//
|
||||
// root kcb must be valid and has only our "artificial" refcount on it
|
||||
//
|
||||
ASSERT( RootKcb != NULL );
|
||||
|
||||
if( RootKcb->RefCount > 1 ) {
|
||||
//
|
||||
// somebody else must've gotten in between dropping/reacquiring the reglock
|
||||
// and opened a handle inside this hive; bad luck, we can't unload
|
||||
//
|
||||
CmpUnlockRegistry();
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT_KCB(RootKcb);
|
||||
|
||||
Cell = RootKcb->KeyCell;
|
||||
Status = CmUnloadKey(RootKcb,0,CM_UNLOAD_REG_LOCKED_EX);
|
||||
ASSERT( (Status != STATUS_CANNOT_DELETE) && (Status != STATUS_INVALID_PARAMETER) );
|
||||
|
||||
if(NT_SUCCESS(Status)) {
|
||||
// CmUnloadKey already released the lock
|
||||
CmpLockRegistry();
|
||||
CmpDereferenceKeyControlBlock(RootKcb);
|
||||
}
|
||||
CmpUnlockRegistry();
|
||||
}
|
||||
|
||||
|
||||
349
base/ntos/config/cmdown.c
Normal file
349
base/ntos/config/cmdown.c
Normal file
@ -0,0 +1,349 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
cmdown.c
|
||||
|
||||
Abstract:
|
||||
|
||||
This module cleans up all the memory used by CM.
|
||||
|
||||
This routine is intended to be called at system shutdown
|
||||
in order to detect memory leaks. It is supposed to free
|
||||
all registry data that is not freed by CmShutdownSystem.
|
||||
|
||||
--*/
|
||||
|
||||
#include "cmp.h"
|
||||
|
||||
//
|
||||
// externals
|
||||
//
|
||||
extern PUCHAR CmpStashBuffer;
|
||||
extern ULONG CmpDelayedCloseSize;
|
||||
|
||||
extern BOOLEAN HvShutdownComplete;
|
||||
|
||||
extern BOOLEAN CmFirstTime;
|
||||
|
||||
extern HIVE_LIST_ENTRY CmpMachineHiveList[];
|
||||
|
||||
VOID
|
||||
CmpFreeAllMemory(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
CmpDereferenceNameControlBlockWithLock(
|
||||
PCM_NAME_CONTROL_BLOCK Ncb
|
||||
);
|
||||
|
||||
VOID
|
||||
CmpDumpKeyBodyList(
|
||||
IN PCM_KEY_CONTROL_BLOCK kcb,
|
||||
IN PULONG Count,
|
||||
IN PVOID Context
|
||||
);
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE,CmpFreeAllMemory)
|
||||
#pragma alloc_text(PAGE,CmShutdownSystem)
|
||||
#endif
|
||||
|
||||
|
||||
VOID
|
||||
CmpFreeAllMemory(
|
||||
VOID
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
- All hives are freed
|
||||
- KCB table is freed
|
||||
- Name hash table is freed
|
||||
- delay close table is freed - question: We need to clean/free all delayed close KCBs
|
||||
- all notifications/postblocks-aso.
|
||||
|
||||
* equivalent with MmReleaseAllMemory
|
||||
|
||||
Arguments:
|
||||
|
||||
|
||||
Return Value:
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
|
||||
PCMHIVE CmHive;
|
||||
LONG i;
|
||||
PCM_KEY_CONTROL_BLOCK KeyControlBlock;
|
||||
PLIST_ENTRY NotifyPtr;
|
||||
PCM_NOTIFY_BLOCK NotifyBlock;
|
||||
PCM_POST_BLOCK PostBlock;
|
||||
PCM_KEY_HASH Current;
|
||||
PLIST_ENTRY AnchorAddr;
|
||||
ULONG Count;
|
||||
BOOLEAN MessageDisplayed;
|
||||
|
||||
CmpRunDownDelayDerefKCBEngine(NULL,TRUE);
|
||||
//
|
||||
// Iterate through the list of the hives in the system
|
||||
//
|
||||
while (IsListEmpty(&CmpHiveListHead) == FALSE) {
|
||||
//
|
||||
// Remove the hive from the list
|
||||
//
|
||||
CmHive = (PCMHIVE)RemoveHeadList(&CmpHiveListHead);
|
||||
CmHive = (PCMHIVE)CONTAINING_RECORD(CmHive,
|
||||
CMHIVE,
|
||||
HiveList);
|
||||
|
||||
//
|
||||
// close hive handles (the ones that are open)
|
||||
//
|
||||
for (i=0; i<HFILE_TYPE_MAX; i++) {
|
||||
// these should be closed by CmShutdownSystem
|
||||
ASSERT( CmHive->FileHandles[i] == NULL );
|
||||
}
|
||||
|
||||
//
|
||||
// free the hive lock and view lock
|
||||
//
|
||||
CmpFreeMutex(CmHive->ViewLock);
|
||||
#if DBG
|
||||
CmpFreeResource(CmHive->FlusherLock);
|
||||
#endif
|
||||
|
||||
//
|
||||
// Spew in the debugger the names of the keynodes having notifies still set
|
||||
//
|
||||
NotifyPtr = &(CmHive->NotifyList);
|
||||
NotifyPtr = NotifyPtr->Flink;
|
||||
MessageDisplayed = FALSE;
|
||||
while( NotifyPtr != NULL ) {
|
||||
NotifyBlock = CONTAINING_RECORD(NotifyPtr, CM_NOTIFY_BLOCK, HiveList);
|
||||
|
||||
AnchorAddr = &(NotifyBlock->PostList);
|
||||
PostBlock = (PCM_POST_BLOCK)(NotifyBlock->PostList.Flink);
|
||||
//
|
||||
// walk through the list and spew the keynames and postblock types.
|
||||
//
|
||||
while ( PostBlock != (PCM_POST_BLOCK)AnchorAddr ) {
|
||||
PostBlock = CONTAINING_RECORD(PostBlock,
|
||||
CM_POST_BLOCK,
|
||||
NotifyList);
|
||||
|
||||
if( PostBlock->PostKeyBody ) {
|
||||
if( MessageDisplayed == FALSE ){
|
||||
MessageDisplayed = TRUE;
|
||||
DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"Dumping untriggered notifications for hive (%lx) (%.*S) \n\n",CmHive,
|
||||
HBASE_NAME_ALLOC / sizeof(WCHAR),CmHive->Hive.BaseBlock->FileName);
|
||||
}
|
||||
switch (PostBlockType(PostBlock)) {
|
||||
case PostSynchronous:
|
||||
DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"Synchronous ");
|
||||
break;
|
||||
case PostAsyncUser:
|
||||
DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"AsyncUser ");
|
||||
break;
|
||||
case PostAsyncKernel:
|
||||
DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"AsyncKernel ");
|
||||
break;
|
||||
}
|
||||
DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"Notification, PostBlock %p not triggered on KCB %p\n",PostBlock,
|
||||
PostBlock->PostKeyBody->KeyBody->KeyControlBlock);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// skip to the next element
|
||||
//
|
||||
PostBlock = (PCM_POST_BLOCK)(PostBlock->NotifyList.Flink);
|
||||
|
||||
}
|
||||
NotifyPtr = NotifyPtr->Flink;
|
||||
}
|
||||
|
||||
//
|
||||
// free security cache
|
||||
//
|
||||
CmpDestroySecurityCache (CmHive);
|
||||
|
||||
//
|
||||
// free the hv level structure
|
||||
//
|
||||
HvFreeHive(&(CmHive->Hive));
|
||||
|
||||
//
|
||||
// free the cm level structure
|
||||
//
|
||||
CmpFree(CmHive, sizeof(CMHIVE));
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Now free the CM globals
|
||||
//
|
||||
|
||||
// the stash buffer
|
||||
if( CmpStashBuffer != NULL ) {
|
||||
ExFreePool( CmpStashBuffer );
|
||||
}
|
||||
|
||||
//
|
||||
// Spew open handles and associated processes
|
||||
//
|
||||
Count = 0;
|
||||
MessageDisplayed = FALSE;
|
||||
for (i=0; i<(LONG)CmpHashTableSize; i++) {
|
||||
Current = CmpCacheTable[i].Entry;
|
||||
while (Current) {
|
||||
KeyControlBlock = CONTAINING_RECORD(Current, CM_KEY_CONTROL_BLOCK, KeyHash);
|
||||
if( MessageDisplayed == FALSE ){
|
||||
MessageDisplayed = TRUE;
|
||||
DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"\nDumping open handles : \n\n");
|
||||
}
|
||||
CmpDumpKeyBodyList(KeyControlBlock,&Count,NULL);
|
||||
Current = Current->NextHash;
|
||||
}
|
||||
}
|
||||
|
||||
if( Count != 0 ) {
|
||||
//
|
||||
// there some open handles; bugcheck
|
||||
//
|
||||
CM_BUGCHECK( REGISTRY_ERROR,HANDLES_STILL_OPEN_AT_SHUTDOWN,1,Count,0);
|
||||
}
|
||||
|
||||
//
|
||||
// in case of private alloc, free pages
|
||||
//
|
||||
CmpDestroyCmPrivateAlloc();
|
||||
CmpDestroyCmPrivateDelayAlloc();
|
||||
//
|
||||
// For the 3 tables below, the objects actually pointed from inside
|
||||
// should be cleaned up (freed) at the last handle closure time
|
||||
// the related handles are closed
|
||||
//
|
||||
// KCB cache table
|
||||
ASSERT( CmpCacheTable != NULL );
|
||||
ExFreePool(CmpCacheTable);
|
||||
|
||||
// NameCacheTable
|
||||
ASSERT( CmpNameCacheTable != NULL );
|
||||
ExFreePool( CmpNameCacheTable );
|
||||
|
||||
|
||||
}
|
||||
|
||||
VOID
|
||||
CmShutdownSystem(
|
||||
VOID
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Shuts down the registry.
|
||||
|
||||
Arguments:
|
||||
|
||||
NONE
|
||||
|
||||
Return Value:
|
||||
|
||||
NONE
|
||||
|
||||
--*/
|
||||
{
|
||||
|
||||
PLIST_ENTRY p;
|
||||
PCMHIVE CmHive;
|
||||
NTSTATUS Status;
|
||||
PVOID RegistryRoot;
|
||||
|
||||
CM_PAGED_CODE();
|
||||
|
||||
if (CmpRegistryRootHandle) {
|
||||
Status = ObReferenceObjectByHandle(CmpRegistryRootHandle,
|
||||
KEY_READ,
|
||||
NULL,
|
||||
KernelMode,
|
||||
&RegistryRoot,
|
||||
NULL);
|
||||
|
||||
if (NT_SUCCESS(Status)) {
|
||||
// We want to dereference the object twice -- once for the
|
||||
// reference we just made, and once for the reference
|
||||
// fromCmpCreateRegistryRoot.
|
||||
ObDereferenceObject(RegistryRoot);
|
||||
ObDereferenceObject(RegistryRoot);
|
||||
}
|
||||
|
||||
ObCloseHandle(CmpRegistryRootHandle, KernelMode);
|
||||
}
|
||||
|
||||
CmpLockRegistryExclusive();
|
||||
|
||||
//
|
||||
// Stop the workers; only if registry has been initializeed
|
||||
//
|
||||
if( CmFirstTime == FALSE ) {
|
||||
CmpShutdownWorkers();
|
||||
}
|
||||
|
||||
//
|
||||
// shut down the registry
|
||||
//
|
||||
CmpDoFlushAll(TRUE);
|
||||
|
||||
//
|
||||
// try to compress the system hive
|
||||
//
|
||||
CmCompressKey( &(CmpMachineHiveList[SYSTEM_HIVE_INDEX].CmHive->Hive) );
|
||||
|
||||
//
|
||||
// close all the hive files
|
||||
//
|
||||
p = CmpHiveListHead.Flink;
|
||||
while(p != &CmpHiveListHead) {
|
||||
CmHive = CONTAINING_RECORD(p, CMHIVE, HiveList);
|
||||
//
|
||||
// we need to unmap all views mapped for this hive first
|
||||
//
|
||||
CmpDestroyHiveViewList(CmHive);
|
||||
CmpUnJoinClassOfTrust(CmHive);
|
||||
//
|
||||
// dereference the fileobject (if any).
|
||||
//
|
||||
CmpDropFileObjectForHive(CmHive);
|
||||
|
||||
//
|
||||
// now we can safely close all the handles
|
||||
//
|
||||
CmpCmdHiveClose(CmHive);
|
||||
|
||||
p=p->Flink;
|
||||
}
|
||||
|
||||
HvShutdownComplete = TRUE; // Tell HvSyncHive to ignore all further requests
|
||||
|
||||
if((PoCleanShutdownEnabled() & PO_CLEAN_SHUTDOWN_REGISTRY) && (CmFirstTime == FALSE)){
|
||||
//
|
||||
// Free aux memory used internally by CM
|
||||
//
|
||||
CmpFreeAllMemory();
|
||||
}
|
||||
|
||||
CmpUnlockRegistry();
|
||||
return;
|
||||
}
|
||||
852
base/ntos/config/cmgquota.c
Normal file
852
base/ntos/config/cmgquota.c
Normal file
@ -0,0 +1,852 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
cmgquota.c
|
||||
|
||||
Abstract:
|
||||
|
||||
The module contains CM routines to support Global Quota
|
||||
|
||||
Global Quota has little to do with NT's standard per-process/user
|
||||
quota system. Global Quota is waying of controlling the aggregate
|
||||
resource usage of the entire registry. It is used to manage space
|
||||
consumption by objects which user apps create, but which are persistent
|
||||
and therefore cannot be assigned to the quota of a user app.
|
||||
|
||||
Global Quota prevents the registry from consuming all of paged
|
||||
pool, and indirectly controls how much disk it can consume.
|
||||
Like the release 1 file systems, a single app can fill all the
|
||||
space in the registry, but at least it cannot kill the system.
|
||||
|
||||
Memory objects used for known short times and protected by
|
||||
serialization, or billable as quota objects, are not counted
|
||||
in the global quota.
|
||||
|
||||
--*/
|
||||
|
||||
#include "cmp.h"
|
||||
|
||||
VOID
|
||||
CmpSystemHiveHysteresisWorker(
|
||||
IN PVOID WorkItem
|
||||
);
|
||||
|
||||
VOID
|
||||
CmpRaiseSelfHealWarningWorker(
|
||||
IN PVOID Arg
|
||||
);
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE,CmpClaimGlobalQuota)
|
||||
#pragma alloc_text(PAGE,CmpReleaseGlobalQuota)
|
||||
#pragma alloc_text(PAGE,CmpSetGlobalQuotaAllowed)
|
||||
#pragma alloc_text(PAGE,CmpQuotaWarningWorker)
|
||||
#pragma alloc_text(PAGE,CmQueryRegistryQuotaInformation)
|
||||
#pragma alloc_text(PAGE,CmSetRegistryQuotaInformation)
|
||||
#pragma alloc_text(PAGE,CmpCanGrowSystemHive)
|
||||
#pragma alloc_text(PAGE,CmpSystemQuotaWarningWorker)
|
||||
#pragma alloc_text(INIT,CmpComputeGlobalQuotaAllowed)
|
||||
#pragma alloc_text(PAGE,CmpSystemHiveHysteresisWorker)
|
||||
#pragma alloc_text(PAGE,CmpUpdateSystemHiveHysteresis)
|
||||
#pragma alloc_text(PAGE,CmRegisterSystemHiveLimitCallback)
|
||||
#pragma alloc_text(PAGE,CmpRaiseSelfHealWarning)
|
||||
#pragma alloc_text(PAGE,CmpRaiseSelfHealWarningForSystemHives)
|
||||
#pragma alloc_text(PAGE,CmpRaiseSelfHealWarningWorker)
|
||||
#endif
|
||||
|
||||
//
|
||||
// Registry control values
|
||||
//
|
||||
#define CM_DEFAULT_RATIO (3)
|
||||
#define CM_LIMIT_RATIO(x) ((x / 10) * 8)
|
||||
#define CM_MINIMUM_GLOBAL_QUOTA (16 *1024 * 1024)
|
||||
|
||||
//
|
||||
// Percent of used registry quota that triggers a hard error
|
||||
// warning popup.
|
||||
//
|
||||
#define CM_REGISTRY_WARNING_LEVEL (95)
|
||||
|
||||
//
|
||||
// System hive hard quota limit
|
||||
//
|
||||
// For an x86 3GB system we set the limit at 12MB for now. Needs some MM changes before we
|
||||
// bump this up.
|
||||
// For an x86 non-3GB system, we set the limit at 1/4 of physical memory
|
||||
// For IA-64 we set the limit at 32MB
|
||||
//
|
||||
|
||||
#define _200MB (200 *1024 * 1024)
|
||||
|
||||
#if defined(_X86_)
|
||||
#define CM_SYSTEM_HIVE_LIMIT_SIZE (min(MmNumberOfPhysicalPages / 4, _200MB >> PAGE_SHIFT) * PAGE_SIZE)
|
||||
#else
|
||||
#define CM_SYSTEM_HIVE_LIMIT_SIZE (32 * 1024 * 1024)
|
||||
#endif
|
||||
|
||||
#define CM_SYSTEM_HIVE_WARNING_SIZE ((CM_SYSTEM_HIVE_LIMIT_SIZE*9)/10)
|
||||
|
||||
|
||||
extern ULONG CmRegistrySizeLimit;
|
||||
extern ULONG CmRegistrySizeLimitLength;
|
||||
extern ULONG CmRegistrySizeLimitType;
|
||||
|
||||
//
|
||||
// Maximum number of bytes of Global Quota the registry may use.
|
||||
// Set to largest positive number for use in boot. Will be set down
|
||||
// based on pool and explicit registry values.
|
||||
//
|
||||
extern SIZE_T CmpGlobalQuota;
|
||||
extern SIZE_T CmpGlobalQuotaAllowed;
|
||||
|
||||
//
|
||||
// Mark that will trigger the low-on-quota popup
|
||||
//
|
||||
extern SIZE_T CmpGlobalQuotaWarning;
|
||||
extern SIZE_T MmSizeOfPagedPoolInBytes;
|
||||
|
||||
//
|
||||
// Indicate whether the popup has been triggered yet or not.
|
||||
//
|
||||
extern BOOLEAN CmpQuotaWarningPopupDisplayed;
|
||||
extern BOOLEAN CmpSystemQuotaWarningPopupDisplayed;
|
||||
|
||||
//
|
||||
// GQ actually in use
|
||||
//
|
||||
extern SIZE_T CmpGlobalQuotaUsed;
|
||||
|
||||
extern HIVE_LIST_ENTRY CmpMachineHiveList[];
|
||||
|
||||
VOID
|
||||
CmQueryRegistryQuotaInformation(
|
||||
__inout PSYSTEM_REGISTRY_QUOTA_INFORMATION RegistryQuotaInformation
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Returns the registry quota information
|
||||
|
||||
Arguments:
|
||||
|
||||
RegistryQuotaInformation - Supplies pointer to buffer that will return
|
||||
the registry quota information.
|
||||
|
||||
Return Value:
|
||||
|
||||
None.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
RegistryQuotaInformation->RegistryQuotaAllowed = (ULONG) CmpGlobalQuota;
|
||||
RegistryQuotaInformation->RegistryQuotaUsed = (ULONG) CmpGlobalQuotaUsed;
|
||||
RegistryQuotaInformation->PagedPoolSize = MmSizeOfPagedPoolInBytes;
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
CmSetRegistryQuotaInformation(
|
||||
__in PSYSTEM_REGISTRY_QUOTA_INFORMATION RegistryQuotaInformation
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Sets the registry quota information. The caller is assumed to have
|
||||
completed the necessary security checks already.
|
||||
|
||||
Arguments:
|
||||
|
||||
RegistryQuotaInformation - Supplies pointer to buffer that provides
|
||||
the new registry quota information.
|
||||
|
||||
Return Value:
|
||||
|
||||
None.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
CmpGlobalQuota = RegistryQuotaInformation->RegistryQuotaAllowed;
|
||||
|
||||
//
|
||||
// Sanity checks against insane values
|
||||
//
|
||||
if (CmpGlobalQuota > CM_WRAP_LIMIT) {
|
||||
CmpGlobalQuota = CM_WRAP_LIMIT;
|
||||
}
|
||||
if (CmpGlobalQuota < CM_MINIMUM_GLOBAL_QUOTA) {
|
||||
CmpGlobalQuota = CM_MINIMUM_GLOBAL_QUOTA;
|
||||
}
|
||||
|
||||
//
|
||||
// Recompute the warning level
|
||||
//
|
||||
CmpGlobalQuotaWarning = CM_REGISTRY_WARNING_LEVEL * (CmpGlobalQuota / 100);
|
||||
|
||||
CmpGlobalQuotaAllowed = CmpGlobalQuota;
|
||||
}
|
||||
|
||||
VOID
|
||||
CmpQuotaWarningWorker(
|
||||
IN PVOID WorkItem
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Displays hard error popup that indicates the registry quota is
|
||||
running out.
|
||||
|
||||
Arguments:
|
||||
|
||||
WorkItem - Supplies pointer to the work item. This routine will
|
||||
free the work item.
|
||||
|
||||
Return Value:
|
||||
|
||||
None.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
NTSTATUS Status;
|
||||
ULONG Response;
|
||||
|
||||
ExFreePool(WorkItem);
|
||||
|
||||
Status = ExRaiseHardError(STATUS_REGISTRY_QUOTA_LIMIT,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
OptionOk,
|
||||
&Response);
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN
|
||||
CmpClaimGlobalQuota(
|
||||
IN ULONG Size
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
If CmpGlobalQuotaUsed + Size >= CmpGlobalQuotaAllowed, return
|
||||
false. Otherwise, increment CmpGlobalQuotaUsed, in effect claiming
|
||||
the requested GlobalQuota.
|
||||
|
||||
Arguments:
|
||||
|
||||
Size - number of bytes of GlobalQuota caller wants to claim
|
||||
|
||||
Return Value:
|
||||
|
||||
TRUE - Claim succeeded, and has been counted in Used GQ
|
||||
|
||||
FALSE - Claim failed, nothing counted in GQ.
|
||||
|
||||
--*/
|
||||
{
|
||||
InterlockedExchangeAdd((PLONG)&CmpGlobalQuotaUsed, Size);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
CmpReleaseGlobalQuota(
|
||||
IN ULONG Size
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
If Size <= CmpGlobalQuotaUsed, then decrement it. Else BugCheck.
|
||||
|
||||
Arguments:
|
||||
|
||||
Size - number of bytes of GlobalQuota caller wants to release
|
||||
|
||||
Return Value:
|
||||
|
||||
NONE.
|
||||
|
||||
--*/
|
||||
{
|
||||
if (Size > CmpGlobalQuotaUsed) {
|
||||
CM_BUGCHECK(REGISTRY_ERROR,QUOTA_ERROR,1,0,0);
|
||||
}
|
||||
|
||||
InterlockedExchangeAdd((PLONG)&CmpGlobalQuotaUsed, -(LONG)Size);
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
CmpComputeGlobalQuotaAllowed(
|
||||
VOID
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Compute CmpGlobalQuota based on:
|
||||
(a) Size of paged pool
|
||||
(b) Explicit user registry commands to set registry GQ
|
||||
|
||||
Return Value:
|
||||
|
||||
NONE.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
SIZE_T PagedLimit;
|
||||
|
||||
PagedLimit = (ULONG)(CM_LIMIT_RATIO(MmSizeOfPagedPoolInBytes));
|
||||
|
||||
if ((CmRegistrySizeLimitLength != 4) ||
|
||||
(CmRegistrySizeLimitType != REG_DWORD) ||
|
||||
(CmRegistrySizeLimit == 0))
|
||||
{
|
||||
//
|
||||
// If no value at all, or value of wrong type, or set to
|
||||
// zero, use internally computed default
|
||||
//
|
||||
CmpGlobalQuota = (ULONG)(MmSizeOfPagedPoolInBytes / CM_DEFAULT_RATIO);
|
||||
|
||||
} else if (CmRegistrySizeLimit >= PagedLimit) {
|
||||
//
|
||||
// If more than computed upper bound, use computed upper bound
|
||||
//
|
||||
CmpGlobalQuota = PagedLimit;
|
||||
|
||||
} else {
|
||||
//
|
||||
// Use the set size
|
||||
//
|
||||
CmpGlobalQuota = CmRegistrySizeLimit;
|
||||
|
||||
}
|
||||
|
||||
if (CmpGlobalQuota > CM_WRAP_LIMIT) {
|
||||
CmpGlobalQuota = CM_WRAP_LIMIT;
|
||||
}
|
||||
if (CmpGlobalQuota < CM_MINIMUM_GLOBAL_QUOTA) {
|
||||
CmpGlobalQuota = CM_MINIMUM_GLOBAL_QUOTA;
|
||||
}
|
||||
|
||||
CmpGlobalQuotaWarning = CM_REGISTRY_WARNING_LEVEL * (CmpGlobalQuota / 100);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
CmpSetGlobalQuotaAllowed(
|
||||
VOID
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Enables registry quota
|
||||
|
||||
NOTE: Do NOT put this in init segment, we call it after
|
||||
that code has been freed!
|
||||
|
||||
Return Value:
|
||||
|
||||
NONE.
|
||||
|
||||
--*/
|
||||
{
|
||||
CmpGlobalQuotaAllowed = CmpGlobalQuota;
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN
|
||||
CmpCanGrowSystemHive(
|
||||
IN PHHIVE Hive,
|
||||
IN ULONG NewLength
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Checks if the system hive is allowed to grow with the specified amount
|
||||
of data (using the hard quota limit on the system hive)
|
||||
|
||||
Return Value:
|
||||
|
||||
NONE.
|
||||
|
||||
--*/
|
||||
{
|
||||
PCMHIVE CmHive;
|
||||
PWORK_QUEUE_ITEM WorkItem;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
CmHive = (PCMHIVE)CONTAINING_RECORD(Hive,CMHIVE,Hive);
|
||||
|
||||
if( CmHive != CmpMachineHiveList[SYSTEM_HIVE_INDEX].CmHive ) {
|
||||
//
|
||||
// not the system hive, bail out
|
||||
//
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// account for the header.
|
||||
NewLength += HBLOCK_SIZE;
|
||||
if( NewLength > CM_SYSTEM_HIVE_LIMIT_SIZE ) {
|
||||
//
|
||||
// this is bad; we may not be able to boot next time !!!
|
||||
//
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if( (NewLength > CM_SYSTEM_HIVE_WARNING_SIZE) &&
|
||||
(!CmpSystemQuotaWarningPopupDisplayed) &&
|
||||
(ExReadyForErrors)
|
||||
) {
|
||||
//
|
||||
// we're above the warning level, queue work item to display popup
|
||||
//
|
||||
WorkItem = ExAllocatePool(NonPagedPool, sizeof(WORK_QUEUE_ITEM));
|
||||
if (WorkItem != NULL) {
|
||||
|
||||
CmpSystemQuotaWarningPopupDisplayed = TRUE;
|
||||
ExInitializeWorkItem(WorkItem,
|
||||
CmpSystemQuotaWarningWorker,
|
||||
WorkItem);
|
||||
ExQueueWorkItem(WorkItem, DelayedWorkQueue);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
CmpSystemQuotaWarningWorker(
|
||||
IN PVOID WorkItem
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Displays hard error popup that indicates the hard quota limit
|
||||
on the system hive is running out.
|
||||
|
||||
Arguments:
|
||||
|
||||
WorkItem - Supplies pointer to the work item. This routine will
|
||||
free the work item.
|
||||
|
||||
Return Value:
|
||||
|
||||
None.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
NTSTATUS Status;
|
||||
ULONG Response;
|
||||
|
||||
ExFreePool(WorkItem);
|
||||
|
||||
Status = ExRaiseHardError(STATUS_REGISTRY_QUOTA_LIMIT,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
OptionOk,
|
||||
&Response);
|
||||
}
|
||||
|
||||
//
|
||||
// Pnp API
|
||||
//
|
||||
ULONG CmpSystemHiveHysteresisLow = 0;
|
||||
ULONG CmpSystemHiveHysteresisHigh = 0;
|
||||
PVOID CmpSystemHiveHysteresisContext = NULL;
|
||||
PCM_HYSTERESIS_CALLBACK CmpSystemHiveHysteresisCallback = NULL;
|
||||
ULONG CmpSystemHiveHysteresisHitRatio = 0;
|
||||
BOOLEAN CmpSystemHiveHysteresisLowSeen = FALSE;
|
||||
BOOLEAN CmpSystemHiveHysteresisHighSeen = FALSE;
|
||||
|
||||
VOID
|
||||
CmpSystemHiveHysteresisWorker(
|
||||
IN PVOID WorkItem
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Calls the hysteresis callback
|
||||
|
||||
Arguments:
|
||||
|
||||
WorkItem - Supplies pointer to the work item. This routine will
|
||||
free the work item.
|
||||
|
||||
Return Value:
|
||||
|
||||
None.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
PCM_HYSTERESIS_CALLBACK Callback;
|
||||
|
||||
ExFreePool(WorkItem);
|
||||
|
||||
Callback = CmpSystemHiveHysteresisCallback;
|
||||
|
||||
if( Callback ) {
|
||||
(*Callback)(CmpSystemHiveHysteresisContext,CmpSystemHiveHysteresisHitRatio);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
CmpUpdateSystemHiveHysteresis( PHHIVE Hive,
|
||||
ULONG NewLength,
|
||||
ULONG OldLength
|
||||
)
|
||||
{
|
||||
PCMHIVE CmHive;
|
||||
PWORK_QUEUE_ITEM WorkItem;
|
||||
ULONG CurrentRatio;
|
||||
BOOLEAN DoWorkItem = FALSE;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
CmHive = (PCMHIVE)CONTAINING_RECORD(Hive,CMHIVE,Hive);
|
||||
|
||||
if( (!CmpSystemHiveHysteresisCallback) || (CmHive != CmpMachineHiveList[SYSTEM_HIVE_INDEX].CmHive) ) {
|
||||
//
|
||||
// not the system hive, bail out
|
||||
//
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT( NewLength != OldLength );
|
||||
|
||||
//
|
||||
// compute current ratio; account for the header first
|
||||
//
|
||||
CurrentRatio = NewLength + HBLOCK_SIZE;
|
||||
CurrentRatio *= 100;
|
||||
CurrentRatio /= CM_SYSTEM_HIVE_LIMIT_SIZE;
|
||||
|
||||
if( NewLength > OldLength ) {
|
||||
//
|
||||
// hive is growing
|
||||
//
|
||||
if( (CmpSystemHiveHysteresisHighSeen == FALSE) && (CurrentRatio > CmpSystemHiveHysteresisHigh) ) {
|
||||
//
|
||||
// we reached high; see if low has already been hit and queue work item
|
||||
//
|
||||
CmpSystemHiveHysteresisHighSeen = TRUE;
|
||||
if( TRUE == CmpSystemHiveHysteresisLowSeen ) {
|
||||
//
|
||||
// low to high; queue workitem
|
||||
//
|
||||
CmpSystemHiveHysteresisHitRatio = CurrentRatio;
|
||||
DoWorkItem = TRUE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// hive is shrinking
|
||||
//
|
||||
if( (FALSE == CmpSystemHiveHysteresisLowSeen) && (CurrentRatio < CmpSystemHiveHysteresisLow ) ) {
|
||||
//
|
||||
// we reached low; see if low has been hit and queue work item
|
||||
//
|
||||
CmpSystemHiveHysteresisLowSeen = TRUE;
|
||||
if( TRUE == CmpSystemHiveHysteresisHighSeen ) {
|
||||
//
|
||||
// high to low; queue workitem
|
||||
//
|
||||
CmpSystemHiveHysteresisHitRatio = CurrentRatio;
|
||||
DoWorkItem = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( DoWorkItem ) {
|
||||
ASSERT( CmpSystemHiveHysteresisLowSeen && CmpSystemHiveHysteresisHighSeen );
|
||||
|
||||
WorkItem = ExAllocatePool(NonPagedPool, sizeof(WORK_QUEUE_ITEM));
|
||||
if (WorkItem != NULL) {
|
||||
|
||||
ExInitializeWorkItem(WorkItem,
|
||||
CmpSystemHiveHysteresisWorker,
|
||||
WorkItem);
|
||||
ExQueueWorkItem(WorkItem, DelayedWorkQueue);
|
||||
}
|
||||
//
|
||||
// reset state so we can fire again later
|
||||
//
|
||||
CmpSystemHiveHysteresisLowSeen = FALSE;
|
||||
CmpSystemHiveHysteresisHighSeen = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
ULONG
|
||||
CmRegisterSystemHiveLimitCallback(
|
||||
__in ULONG Low,
|
||||
__in ULONG High,
|
||||
__in PVOID Ref,
|
||||
__in PCM_HYSTERESIS_CALLBACK Callback
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine registers a hysteresis for the system hive limit ratio.
|
||||
We will call the callback :
|
||||
|
||||
a. the system hive goes above High from below Low
|
||||
b. the system hive goes below Low from above High
|
||||
|
||||
Arguments:
|
||||
|
||||
Low, High - specifies the hysteresis
|
||||
|
||||
Ref - Context to give back to the callback
|
||||
|
||||
Callback - callback routine.
|
||||
|
||||
Return Value:
|
||||
|
||||
current ratio 0 - 100
|
||||
|
||||
--*/
|
||||
{
|
||||
ULONG Length;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
if( CmpMachineHiveList[SYSTEM_HIVE_INDEX].CmHive ) {
|
||||
Length = CmpMachineHiveList[SYSTEM_HIVE_INDEX].CmHive->Hive.BaseBlock->Length + HBLOCK_SIZE;
|
||||
|
||||
Length *= 100;
|
||||
Length /= CM_SYSTEM_HIVE_LIMIT_SIZE;
|
||||
} else {
|
||||
Length = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// allow only one call per system uptime.
|
||||
//
|
||||
if( CmpSystemHiveHysteresisCallback == NULL ) {
|
||||
CmpSystemHiveHysteresisLow = Low;
|
||||
CmpSystemHiveHysteresisHigh = High;
|
||||
CmpSystemHiveHysteresisContext = Ref;
|
||||
CmpSystemHiveHysteresisCallback = Callback;
|
||||
//
|
||||
// set state vars
|
||||
//
|
||||
if( Length <= Low ) {
|
||||
CmpSystemHiveHysteresisLowSeen = TRUE;
|
||||
} else {
|
||||
CmpSystemHiveHysteresisLowSeen = FALSE;
|
||||
}
|
||||
if( Length >= High) {
|
||||
CmpSystemHiveHysteresisHighSeen = TRUE;
|
||||
} else {
|
||||
CmpSystemHiveHysteresisHighSeen = FALSE;
|
||||
}
|
||||
}
|
||||
return Length;
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
CmpHysteresisTest(PVOID Ref, ULONG Level)
|
||||
{
|
||||
UNREFERENCED_PARAMETER (Ref);
|
||||
|
||||
DbgPrint("CmpHysteresisTest called with level = %lu \n",Level);
|
||||
}
|
||||
|
||||
LIST_ENTRY CmpSelfHealQueueListHead;
|
||||
KGUARDED_MUTEX CmpSelfHealQueueLock;
|
||||
BOOLEAN CmpSelfHealWorkerActive = FALSE;
|
||||
|
||||
#define LOCK_SELF_HEAL_QUEUE() KeAcquireGuardedMutex(&CmpSelfHealQueueLock)
|
||||
#define UNLOCK_SELF_HEAL_QUEUE() KeReleaseGuardedMutex(&CmpSelfHealQueueLock)
|
||||
|
||||
typedef struct {
|
||||
PWORK_QUEUE_ITEM WorkItem;
|
||||
LIST_ENTRY SelfHealQueueListEntry;
|
||||
UNICODE_STRING HiveName;
|
||||
//
|
||||
// variable length; name goes here
|
||||
//
|
||||
} CM_SELF_HEAL_WORK_ITEM_PARAMETER, *PCM_SELF_HEAL_WORK_ITEM_PARAMETER;
|
||||
|
||||
VOID
|
||||
CmpRaiseSelfHealWarningWorker(
|
||||
IN PVOID Arg
|
||||
)
|
||||
{
|
||||
PVOID ErrorParameters;
|
||||
ULONG ErrorResponse;
|
||||
PCM_SELF_HEAL_WORK_ITEM_PARAMETER Param;
|
||||
|
||||
Param = (PCM_SELF_HEAL_WORK_ITEM_PARAMETER)Arg;
|
||||
ErrorParameters = &(Param->HiveName);
|
||||
ExRaiseHardError(
|
||||
STATUS_REGISTRY_HIVE_RECOVERED,
|
||||
1,
|
||||
1,
|
||||
(PULONG_PTR)&ErrorParameters,
|
||||
OptionOk,
|
||||
&ErrorResponse
|
||||
);
|
||||
|
||||
//
|
||||
// free what we have allocated
|
||||
//
|
||||
ExFreePool(Param->WorkItem);
|
||||
ExFreePool(Param);
|
||||
|
||||
//
|
||||
// see if there are other self heal warnings to be posted.
|
||||
//
|
||||
LOCK_SELF_HEAL_QUEUE();
|
||||
CmpSelfHealWorkerActive = FALSE;
|
||||
if( IsListEmpty(&CmpSelfHealQueueListHead) == FALSE ) {
|
||||
//
|
||||
// remove head and queue it.
|
||||
//
|
||||
Param = (PCM_SELF_HEAL_WORK_ITEM_PARAMETER)RemoveHeadList(&CmpSelfHealQueueListHead);
|
||||
Param = CONTAINING_RECORD(
|
||||
Param,
|
||||
CM_SELF_HEAL_WORK_ITEM_PARAMETER,
|
||||
SelfHealQueueListEntry
|
||||
);
|
||||
ExQueueWorkItem(Param->WorkItem, DelayedWorkQueue);
|
||||
CmpSelfHealWorkerActive = TRUE;
|
||||
}
|
||||
UNLOCK_SELF_HEAL_QUEUE();
|
||||
}
|
||||
|
||||
VOID
|
||||
CmpRaiseSelfHealWarning(
|
||||
IN PUNICODE_STRING HiveName
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Raise a hard error informing the use the specified hive has been self healed and
|
||||
it might not be entirely consitent
|
||||
|
||||
Arguments:
|
||||
|
||||
Parameter - the hive name.
|
||||
|
||||
Return Value:
|
||||
|
||||
None.
|
||||
|
||||
--*/
|
||||
{
|
||||
PCM_SELF_HEAL_WORK_ITEM_PARAMETER Param;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
//
|
||||
// we're above the warning level, queue work item to display popup
|
||||
//
|
||||
Param = ExAllocatePool(NonPagedPool, sizeof(CM_SELF_HEAL_WORK_ITEM_PARAMETER) + HiveName->Length);
|
||||
if( Param ) {
|
||||
Param->WorkItem = ExAllocatePool(NonPagedPool, sizeof(WORK_QUEUE_ITEM));
|
||||
if(Param->WorkItem != NULL) {
|
||||
Param->HiveName.Length = Param->HiveName.MaximumLength = HiveName->Length;
|
||||
Param->HiveName.Buffer = (PWSTR)(((PUCHAR)Param) + sizeof(CM_SELF_HEAL_WORK_ITEM_PARAMETER));
|
||||
RtlCopyMemory(Param->HiveName.Buffer,HiveName->Buffer,HiveName->Length);
|
||||
ExInitializeWorkItem(Param->WorkItem,
|
||||
CmpRaiseSelfHealWarningWorker,
|
||||
Param);
|
||||
LOCK_SELF_HEAL_QUEUE();
|
||||
if( !CmpSelfHealWorkerActive ) {
|
||||
//
|
||||
// no work item currently; ok to queue one.
|
||||
//
|
||||
ExQueueWorkItem(Param->WorkItem, DelayedWorkQueue);
|
||||
CmpSelfHealWorkerActive = TRUE;
|
||||
} else {
|
||||
//
|
||||
// add it to the end of the list. It'll be picked up when the current work item
|
||||
// completes
|
||||
//
|
||||
InsertTailList(
|
||||
&CmpSelfHealQueueListHead,
|
||||
&(Param->SelfHealQueueListEntry)
|
||||
);
|
||||
}
|
||||
UNLOCK_SELF_HEAL_QUEUE();
|
||||
} else {
|
||||
ExFreePool(Param);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
CmpRaiseSelfHealWarningForSystemHives( )
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Walks the system hivelist and raises a hard error in the event one of the hives has been self healed.
|
||||
|
||||
Intended to be called after controlset has been saved, from inside NtInitializeRegistry
|
||||
(i.e. we have an UI available so it will not stop the machine).
|
||||
|
||||
Arguments:
|
||||
|
||||
Return Value:
|
||||
|
||||
None.
|
||||
|
||||
--*/
|
||||
{
|
||||
ULONG i;
|
||||
UNICODE_STRING Name;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
for (i = 0; i < CM_NUMBER_OF_MACHINE_HIVES; i++) {
|
||||
if( !(CmpMachineHiveList[i].HHiveFlags & HIVE_VOLATILE) && (((PHHIVE)(CmpMachineHiveList[i].CmHive2))->BaseBlock->BootType & HBOOT_SELFHEAL) ) {
|
||||
RtlInitUnicodeString(
|
||||
&Name,
|
||||
CmpMachineHiveList[i].Name
|
||||
);
|
||||
CmpRaiseSelfHealWarning( &Name );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
405
base/ntos/config/cmhook.c
Normal file
405
base/ntos/config/cmhook.c
Normal file
@ -0,0 +1,405 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
cmhook.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Provides routines for implementing callbacks into the registry code.
|
||||
Callbacks are to be used by the virus filter drivers and cluster
|
||||
replication engine.
|
||||
|
||||
--*/
|
||||
#include "cmp.h"
|
||||
|
||||
#define CM_MAX_CALLBACKS 100
|
||||
|
||||
typedef struct _CM_CALLBACK_CONTEXT_BLOCK {
|
||||
LARGE_INTEGER Cookie; // to identify a specific callback for deregistration purposes
|
||||
LIST_ENTRY ThreadListHead; // Active threads inside this callback
|
||||
EX_PUSH_LOCK ThreadListLock; // synchronize access to the above
|
||||
PVOID CallerContext;
|
||||
} CM_CALLBACK_CONTEXT_BLOCK, *PCM_CALLBACK_CONTEXT_BLOCK;
|
||||
|
||||
typedef struct _CM_ACTIVE_NOTIFY_THREAD {
|
||||
LIST_ENTRY ThreadList;
|
||||
PETHREAD Thread;
|
||||
} CM_ACTIVE_NOTIFY_THREAD, *PCM_ACTIVE_NOTIFY_THREAD;
|
||||
|
||||
#define CmpLockContext(Context) ExAcquirePushLockExclusive(&((Context)->ThreadListLock))
|
||||
#define CmpUnlockContext(Context) ExReleasePushLock(&((Context)->ThreadListLock))
|
||||
|
||||
|
||||
#ifdef ALLOC_DATA_PRAGMA
|
||||
#pragma data_seg("PAGEDATA")
|
||||
#endif
|
||||
|
||||
ULONG CmpCallBackCount = 0;
|
||||
EX_CALLBACK CmpCallBackVector[CM_MAX_CALLBACKS] = {0};
|
||||
|
||||
#ifdef ALLOC_DATA_PRAGMA
|
||||
#pragma data_seg()
|
||||
#endif
|
||||
|
||||
VOID
|
||||
CmpInitCallback(VOID);
|
||||
|
||||
BOOLEAN
|
||||
CmpCheckRecursionAndRecordThreadInfo(
|
||||
PCM_CALLBACK_CONTEXT_BLOCK CallbackBlock,
|
||||
PCM_ACTIVE_NOTIFY_THREAD ActiveThreadInfo
|
||||
);
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE,CmRegisterCallback)
|
||||
#pragma alloc_text(PAGE,CmUnRegisterCallback)
|
||||
#pragma alloc_text(PAGE,CmpInitCallback)
|
||||
#pragma alloc_text(PAGE,CmpCallCallBacks)
|
||||
#pragma alloc_text(PAGE,CmpCheckRecursionAndRecordThreadInfo)
|
||||
#endif
|
||||
|
||||
|
||||
NTSTATUS
|
||||
CmRegisterCallback(__in PEX_CALLBACK_FUNCTION Function,
|
||||
__in_opt PVOID Context,
|
||||
__out PLARGE_INTEGER Cookie
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Registers a new callback.
|
||||
|
||||
Arguments:
|
||||
|
||||
|
||||
|
||||
Return Value:
|
||||
|
||||
|
||||
--*/
|
||||
{
|
||||
PEX_CALLBACK_ROUTINE_BLOCK RoutineBlock;
|
||||
ULONG i;
|
||||
PCM_CALLBACK_CONTEXT_BLOCK CmCallbackContext;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
CmCallbackContext = (PCM_CALLBACK_CONTEXT_BLOCK)ExAllocatePoolWithTag (PagedPool,
|
||||
sizeof (CM_CALLBACK_CONTEXT_BLOCK),
|
||||
'bcMC');
|
||||
if( CmCallbackContext == NULL ) {
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
RoutineBlock = ExAllocateCallBack (Function,CmCallbackContext);
|
||||
if( RoutineBlock == NULL ) {
|
||||
ExFreePool(CmCallbackContext);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// init the context
|
||||
//
|
||||
KeQuerySystemTime(&(CmCallbackContext->Cookie));
|
||||
*Cookie = CmCallbackContext->Cookie;
|
||||
InitializeListHead(&(CmCallbackContext->ThreadListHead));
|
||||
ExInitializePushLock(&(CmCallbackContext->ThreadListLock));
|
||||
CmCallbackContext->CallerContext = Context;
|
||||
|
||||
//
|
||||
// find a spot where we could add this callback
|
||||
//
|
||||
for( i=0;i<CM_MAX_CALLBACKS;i++) {
|
||||
if( ExCompareExchangeCallBack (&CmpCallBackVector[i],RoutineBlock,NULL) ) {
|
||||
InterlockedExchangeAdd ((PLONG) &CmpCallBackCount, 1);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// no more callbacks
|
||||
//
|
||||
ExFreePool(CmCallbackContext);
|
||||
ExFreeCallBack(RoutineBlock);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
CmUnRegisterCallback(__in LARGE_INTEGER Cookie)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Unregisters a callback.
|
||||
|
||||
Arguments:
|
||||
|
||||
Return Value:
|
||||
|
||||
|
||||
--*/
|
||||
{
|
||||
ULONG i;
|
||||
PCM_CALLBACK_CONTEXT_BLOCK CmCallbackContext;
|
||||
PEX_CALLBACK_ROUTINE_BLOCK RoutineBlock;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
//
|
||||
// Search for this cookie
|
||||
//
|
||||
for( i=0;i<CM_MAX_CALLBACKS;i++) {
|
||||
RoutineBlock = ExReferenceCallBackBlock(&(CmpCallBackVector[i]) );
|
||||
if( RoutineBlock ) {
|
||||
CmCallbackContext = (PCM_CALLBACK_CONTEXT_BLOCK)ExGetCallBackBlockContext(RoutineBlock);
|
||||
if( CmCallbackContext && (CmCallbackContext->Cookie.QuadPart == Cookie.QuadPart) ) {
|
||||
//
|
||||
// found it
|
||||
//
|
||||
if( ExCompareExchangeCallBack (&CmpCallBackVector[i],NULL,RoutineBlock) ) {
|
||||
InterlockedExchangeAdd ((PLONG) &CmpCallBackCount, -1);
|
||||
|
||||
ExDereferenceCallBackBlock (&(CmpCallBackVector[i]),RoutineBlock);
|
||||
//
|
||||
// wait for others to release their reference, then tear down the structure
|
||||
//
|
||||
ExWaitForCallBacks (RoutineBlock);
|
||||
|
||||
ExFreePool(CmCallbackContext);
|
||||
ExFreeCallBack(RoutineBlock);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
} else {
|
||||
ExDereferenceCallBackBlock (&(CmpCallBackVector[i]),RoutineBlock);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Cm internals
|
||||
//
|
||||
NTSTATUS
|
||||
CmpCallCallBacks (
|
||||
IN REG_NOTIFY_CLASS Type,
|
||||
IN PVOID Argument,
|
||||
IN BOOLEAN Wind,
|
||||
IN REG_NOTIFY_CLASS PostType,
|
||||
IN PVOID Object
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This function calls the callback thats inside a callback structure
|
||||
|
||||
Arguments:
|
||||
|
||||
Type - Nt call selector
|
||||
|
||||
Argument - Caller provided argument to pass on (one of the REG_*_INFORMATION )
|
||||
|
||||
Wind - tells if this is a pre or a post callback
|
||||
|
||||
PostType - matching post notify class
|
||||
|
||||
Object - to be used in case we fail part through.
|
||||
|
||||
Return Value:
|
||||
|
||||
NTSTATUS - STATUS_SUCCESS or error status returned by the first callback
|
||||
|
||||
--*/
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
LONG i;
|
||||
LONG Direction;
|
||||
PEX_CALLBACK_ROUTINE_BLOCK RoutineBlock;
|
||||
PCM_CALLBACK_CONTEXT_BLOCK CmCallbackContext;
|
||||
BOOLEAN InternalUnWind = FALSE;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
if( Wind == TRUE ) {
|
||||
Direction = 1;
|
||||
i = 0;
|
||||
} else {
|
||||
Direction = -1;
|
||||
i = CM_MAX_CALLBACKS - 1;
|
||||
}
|
||||
for(;(i >= 0) && (i < CM_MAX_CALLBACKS);i += Direction) {
|
||||
RoutineBlock = ExReferenceCallBackBlock(&(CmpCallBackVector[i]) );
|
||||
if( RoutineBlock != NULL ) {
|
||||
//
|
||||
// we have a safe reference on this block.
|
||||
//
|
||||
//
|
||||
// record thread on a stack struct, so we don't need to allocate pool for it. We unlink
|
||||
// it from our lists prior to this function exit, so we are on the safe side.
|
||||
//
|
||||
CM_ACTIVE_NOTIFY_THREAD ActiveThreadInfo;
|
||||
|
||||
//
|
||||
// get context info
|
||||
//
|
||||
CmCallbackContext = (PCM_CALLBACK_CONTEXT_BLOCK)ExGetCallBackBlockContext(RoutineBlock);
|
||||
ASSERT( CmCallbackContext != NULL );
|
||||
|
||||
ActiveThreadInfo.Thread = PsGetCurrentThread();
|
||||
#if DBG
|
||||
InitializeListHead(&(ActiveThreadInfo.ThreadList));
|
||||
#endif //DBG
|
||||
|
||||
if( CmpCheckRecursionAndRecordThreadInfo(CmCallbackContext,&ActiveThreadInfo) ) {
|
||||
if( InternalUnWind == TRUE ) {
|
||||
//
|
||||
// this is an internal unwind due to fail part through. need to call posts manually
|
||||
//
|
||||
REG_POST_OPERATION_INFORMATION PostInfo;
|
||||
PostInfo.Object = Object;
|
||||
PostInfo.Status = Status;
|
||||
ExGetCallBackBlockRoutine(RoutineBlock)(CmCallbackContext->CallerContext,(PVOID)(ULONG_PTR)PostType,&PostInfo);
|
||||
// ignore return status.
|
||||
} else {
|
||||
//
|
||||
// regular callback call
|
||||
//
|
||||
Status = ExGetCallBackBlockRoutine(RoutineBlock)(CmCallbackContext->CallerContext,(PVOID)(ULONG_PTR)Type,Argument);
|
||||
if( Wind == FALSE ) {
|
||||
//
|
||||
// always ignore post return calls so they all get a chance to run
|
||||
//
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
//
|
||||
// now that we're down, remove ourselves from the thread list
|
||||
//
|
||||
CmpLockContext(CmCallbackContext);
|
||||
RemoveEntryList(&(ActiveThreadInfo.ThreadList));
|
||||
CmpUnlockContext(CmCallbackContext);
|
||||
} else {
|
||||
ASSERT( IsListEmpty(&(ActiveThreadInfo.ThreadList)) );
|
||||
}
|
||||
|
||||
ExDereferenceCallBackBlock (&(CmpCallBackVector[i]),RoutineBlock);
|
||||
|
||||
if( !NT_SUCCESS(Status) ) {
|
||||
if( Wind == TRUE ) {
|
||||
//
|
||||
// switch direction and start calling the posts
|
||||
//
|
||||
Wind = FALSE;
|
||||
Direction *= -1;
|
||||
InternalUnWind = TRUE;
|
||||
} else if( InternalUnWind == FALSE ) {
|
||||
return Status;
|
||||
}
|
||||
//
|
||||
// else fall through so the unwind completes
|
||||
//
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
VOID
|
||||
CmpInitCallback(VOID)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Init the callback module
|
||||
|
||||
Arguments:
|
||||
|
||||
|
||||
|
||||
Return Value:
|
||||
|
||||
|
||||
--*/
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
CmpCallBackCount = 0;
|
||||
for( i=0;i<CM_MAX_CALLBACKS;i++) {
|
||||
ExInitializeCallBack (&(CmpCallBackVector[i]));
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
CmpCheckRecursionAndRecordThreadInfo(
|
||||
PCM_CALLBACK_CONTEXT_BLOCK CallbackBlock,
|
||||
PCM_ACTIVE_NOTIFY_THREAD ActiveThreadInfo
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Checks if current thread is already inside the callback (recursion avoidance)
|
||||
|
||||
Arguments:
|
||||
|
||||
|
||||
Return Value:
|
||||
|
||||
|
||||
--*/
|
||||
{
|
||||
PLIST_ENTRY AnchorAddr;
|
||||
PCM_ACTIVE_NOTIFY_THREAD CurrentThreadInfo;
|
||||
|
||||
PAGED_CODE();
|
||||
|
||||
CmpLockContext(CallbackBlock);
|
||||
//
|
||||
// walk the ActiveThreadList and see if we are already active
|
||||
//
|
||||
AnchorAddr = &(CallbackBlock->ThreadListHead);
|
||||
CurrentThreadInfo = (PCM_ACTIVE_NOTIFY_THREAD)(CallbackBlock->ThreadListHead.Flink);
|
||||
|
||||
while ( CurrentThreadInfo != (PCM_ACTIVE_NOTIFY_THREAD)AnchorAddr ) {
|
||||
CurrentThreadInfo = CONTAINING_RECORD(
|
||||
CurrentThreadInfo,
|
||||
CM_ACTIVE_NOTIFY_THREAD,
|
||||
ThreadList
|
||||
);
|
||||
if( CurrentThreadInfo->Thread == ActiveThreadInfo->Thread ) {
|
||||
//
|
||||
// already there!
|
||||
//
|
||||
CmpUnlockContext(CallbackBlock);
|
||||
return FALSE;
|
||||
}
|
||||
//
|
||||
// skip to the next element
|
||||
//
|
||||
CurrentThreadInfo = (PCM_ACTIVE_NOTIFY_THREAD)(CurrentThreadInfo->ThreadList.Flink);
|
||||
}
|
||||
|
||||
//
|
||||
// add this thread
|
||||
//
|
||||
InsertTailList(&(CallbackBlock->ThreadListHead), &(ActiveThreadInfo->ThreadList));
|
||||
CmpUnlockContext(CallbackBlock);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
364
base/ntos/config/cmhvlist.c
Normal file
364
base/ntos/config/cmhvlist.c
Normal file
@ -0,0 +1,364 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
cmhvlist.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Code to maintain registry node that lists where the roots of
|
||||
hives are and what files they map to.
|
||||
|
||||
--*/
|
||||
|
||||
#include "cmp.h"
|
||||
|
||||
#define HIVE_LIST L"\\registry\\machine\\system\\currentcontrolset\\control\\hivelist"
|
||||
|
||||
BOOLEAN
|
||||
CmpGetHiveName(
|
||||
PCMHIVE CmHive,
|
||||
PUNICODE_STRING HiveName
|
||||
);
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE,CmpAddToHiveFileList)
|
||||
#pragma alloc_text(PAGE,CmpRemoveFromHiveFileList)
|
||||
#pragma alloc_text(PAGE,CmpGetHiveName)
|
||||
#endif
|
||||
|
||||
|
||||
NTSTATUS
|
||||
CmpAddToHiveFileList(
|
||||
PCMHIVE CmHive
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Add Hive to list of hives and their files in
|
||||
\registry\machine\system\currentcontrolset\control\hivelist
|
||||
|
||||
Arguments:
|
||||
|
||||
HivePath - path to root of hive (e.g. \registry\machine\system)
|
||||
|
||||
CmHive - pointer to CM_HIVE structure for hive.
|
||||
|
||||
Return Value:
|
||||
|
||||
ntstatus
|
||||
|
||||
--*/
|
||||
{
|
||||
#define NAME_BUFFER_SIZE 512
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
HANDLE KeyHandle;
|
||||
NTSTATUS Status;
|
||||
PUCHAR Buffer;
|
||||
ULONG Length;
|
||||
PWSTR FilePath;
|
||||
WCHAR UnicodeNull=UNICODE_NULL;
|
||||
UNICODE_STRING TempName;
|
||||
UNICODE_STRING HivePath;
|
||||
|
||||
//
|
||||
// create/open the hive list key
|
||||
//
|
||||
RtlInitUnicodeString(
|
||||
&TempName,
|
||||
HIVE_LIST
|
||||
);
|
||||
|
||||
InitializeObjectAttributes(
|
||||
&ObjectAttributes,
|
||||
&TempName,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
(HANDLE)NULL,
|
||||
NULL
|
||||
);
|
||||
|
||||
Status = ZwCreateKey(
|
||||
&KeyHandle,
|
||||
KEY_READ | KEY_WRITE,
|
||||
&ObjectAttributes,
|
||||
0,
|
||||
NULL,
|
||||
REG_OPTION_VOLATILE,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"CmpAddToHiveFileList: "));
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"Create/Open of Hive list failed status = %08lx\n", Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// allocate work buffers
|
||||
//
|
||||
Buffer = ExAllocatePool(PagedPool, NAME_BUFFER_SIZE + sizeof(WCHAR));
|
||||
if (Buffer == NULL) {
|
||||
NtClose(KeyHandle);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
//
|
||||
// compute name of hive
|
||||
//
|
||||
if (! CmpGetHiveName(CmHive, &HivePath)) {
|
||||
NtClose(KeyHandle);
|
||||
ExFreePool(Buffer);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// get name of file
|
||||
//
|
||||
if (!(CmHive->Hive.HiveFlags & HIVE_VOLATILE)) {
|
||||
Status = ZwQueryObject(
|
||||
CmHive->FileHandles[HFILE_TYPE_PRIMARY],
|
||||
ObjectNameInformation,
|
||||
(PVOID)Buffer,
|
||||
NAME_BUFFER_SIZE,
|
||||
&Length
|
||||
);
|
||||
Length -= sizeof(UNICODE_STRING);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"CmpAddToHiveFileList: "));
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"Query of name2 failed status = %08lx\n", Status));
|
||||
NtClose(KeyHandle);
|
||||
ExFreePool(HivePath.Buffer);
|
||||
ExFreePool(Buffer);
|
||||
return Status;
|
||||
}
|
||||
FilePath = ((POBJECT_NAME_INFORMATION)Buffer)->Name.Buffer;
|
||||
FilePath[Length/sizeof(WCHAR)] = UNICODE_NULL;
|
||||
Length+=sizeof(WCHAR);
|
||||
} else {
|
||||
FilePath = &UnicodeNull;
|
||||
Length = sizeof(UnicodeNull);
|
||||
}
|
||||
|
||||
//
|
||||
// set entry in list
|
||||
//
|
||||
Status = ZwSetValueKey(
|
||||
KeyHandle,
|
||||
&HivePath,
|
||||
0,
|
||||
REG_SZ,
|
||||
FilePath,
|
||||
Length
|
||||
);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"CmpAddToHiveFileList: "));
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"Set of entry in Hive list failed status = %08lx\n", Status));
|
||||
}
|
||||
|
||||
NtClose(KeyHandle);
|
||||
ExFreePool(HivePath.Buffer);
|
||||
ExFreePool(Buffer);
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
CmpRemoveFromHiveFileList(
|
||||
PUNICODE_STRING EntryName
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Remove hive name from hive file list key
|
||||
|
||||
Arguments:
|
||||
|
||||
CmHive - pointer to CM_HIVE structure for hive.
|
||||
|
||||
Return Value:
|
||||
|
||||
ntstatus
|
||||
|
||||
--*/
|
||||
{
|
||||
NTSTATUS Status;
|
||||
UNICODE_STRING TempName;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
HANDLE KeyHandle;
|
||||
|
||||
//
|
||||
// open the hive list key
|
||||
//
|
||||
RtlInitUnicodeString(
|
||||
&TempName,
|
||||
HIVE_LIST
|
||||
);
|
||||
|
||||
InitializeObjectAttributes(
|
||||
&ObjectAttributes,
|
||||
&TempName,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
(HANDLE)NULL,
|
||||
NULL
|
||||
);
|
||||
|
||||
Status = ZwOpenKey(
|
||||
&KeyHandle,
|
||||
KEY_READ | KEY_WRITE,
|
||||
&ObjectAttributes
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ZwDeleteValueKey(KeyHandle, EntryName);
|
||||
|
||||
NtClose(KeyHandle);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN
|
||||
CmpGetHiveName(
|
||||
PCMHIVE CmHive,
|
||||
PUNICODE_STRING HiveName
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Compute full path to a hive.
|
||||
|
||||
Arguments:
|
||||
|
||||
CmHive - pointer to CmHive structure
|
||||
|
||||
HiveName - supplies pointer to unicode string structure that
|
||||
will be filled in with pointer to name.
|
||||
|
||||
CALL IS EXPECTED TO FREE BUFFER
|
||||
|
||||
Return Value:
|
||||
|
||||
TRUE = it worked, FALSE = it failed (memory)
|
||||
|
||||
--*/
|
||||
{
|
||||
HCELL_INDEX RootCell;
|
||||
HCELL_INDEX LinkCell;
|
||||
PCM_KEY_NODE LinkKey;
|
||||
PCM_KEY_NODE LinkParent;
|
||||
SIZE_T size;
|
||||
SIZE_T rsize;
|
||||
ULONG KeySize;
|
||||
ULONG ParentSize;
|
||||
PWCHAR p;
|
||||
PCM_KEY_NODE EntryKey;
|
||||
|
||||
//
|
||||
// First find the link cell.
|
||||
//
|
||||
RootCell = CmHive->Hive.BaseBlock->RootCell;
|
||||
EntryKey = (PCM_KEY_NODE)HvGetCell((PHHIVE)CmHive, RootCell);
|
||||
if( EntryKey == NULL ) {
|
||||
//
|
||||
// we couldn't map a view for the bin containing this cell
|
||||
//
|
||||
return FALSE;
|
||||
}
|
||||
LinkCell = EntryKey->Parent;
|
||||
HvReleaseCell((PHHIVE)CmHive, RootCell);
|
||||
|
||||
// for master we don't need to count cell usage
|
||||
ASSERT( ((PHHIVE)CmpMasterHive)->ReleaseCellRoutine == NULL );
|
||||
//
|
||||
// Compute the value entry name, which is of the form:
|
||||
// \registry\<parent of link node name>\<link node name>
|
||||
//
|
||||
LinkKey = (PCM_KEY_NODE)HvGetCell((PHHIVE)CmpMasterHive, LinkCell);
|
||||
if( LinkKey == NULL ) {
|
||||
//
|
||||
// we couldn't map a view for the bin containing this cell
|
||||
//
|
||||
return FALSE;
|
||||
}
|
||||
LinkParent = (PCM_KEY_NODE)HvGetCell(
|
||||
(PHHIVE)CmpMasterHive,
|
||||
LinkKey->Parent
|
||||
);
|
||||
if( LinkParent == NULL ) {
|
||||
//
|
||||
// we couldn't map a view for the bin containing this cell
|
||||
//
|
||||
return FALSE;
|
||||
}
|
||||
rsize = wcslen(L"\\REGISTRY\\");
|
||||
|
||||
KeySize = CmpHKeyNameLen(LinkKey);
|
||||
ParentSize = CmpHKeyNameLen(LinkParent);
|
||||
size = KeySize + ParentSize +
|
||||
(rsize * sizeof(WCHAR)) + sizeof(WCHAR);
|
||||
|
||||
HiveName->Buffer = ExAllocatePool(PagedPool, size);
|
||||
if (HiveName->Buffer == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#pragma prefast(suppress:12005, "no overflow. size is bounded by max key length (512)")
|
||||
HiveName->Length = (USHORT)size;
|
||||
HiveName->MaximumLength = (USHORT)size;
|
||||
p = HiveName->Buffer;
|
||||
|
||||
RtlCopyMemory(
|
||||
(PVOID)p,
|
||||
(PVOID)L"\\REGISTRY\\",
|
||||
rsize * sizeof(WCHAR)
|
||||
);
|
||||
p += rsize;
|
||||
|
||||
if (LinkParent->Flags & KEY_COMP_NAME) {
|
||||
CmpCopyCompressedName(p,
|
||||
ParentSize,
|
||||
LinkParent->Name,
|
||||
LinkParent->NameLength);
|
||||
} else {
|
||||
RtlCopyMemory(
|
||||
(PVOID)p,
|
||||
(PVOID)&(LinkParent->Name[0]),
|
||||
ParentSize
|
||||
);
|
||||
}
|
||||
|
||||
p += ParentSize / sizeof(WCHAR);
|
||||
|
||||
*p = OBJ_NAME_PATH_SEPARATOR;
|
||||
p++;
|
||||
|
||||
if (LinkKey->Flags & KEY_COMP_NAME) {
|
||||
CmpCopyCompressedName(p,
|
||||
KeySize,
|
||||
LinkKey->Name,
|
||||
LinkKey->NameLength);
|
||||
|
||||
} else {
|
||||
RtlCopyMemory(
|
||||
(PVOID)p,
|
||||
(PVOID)&(LinkKey->Name[0]),
|
||||
KeySize
|
||||
);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
3093
base/ntos/config/cmindex.c
Normal file
3093
base/ntos/config/cmindex.c
Normal file
File diff suppressed because it is too large
Load Diff
966
base/ntos/config/cminit.c
Normal file
966
base/ntos/config/cminit.c
Normal file
@ -0,0 +1,966 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
cminit.c
|
||||
|
||||
Abstract:
|
||||
|
||||
This module contains init support for the CM level of the
|
||||
config manager/hive.
|
||||
|
||||
--*/
|
||||
|
||||
#include "cmp.h"
|
||||
|
||||
//
|
||||
// Prototypes local to this module
|
||||
//
|
||||
NTSTATUS
|
||||
CmpOpenFileWithExtremePrejudice(
|
||||
OUT PHANDLE Primary,
|
||||
IN POBJECT_ATTRIBUTES Obja,
|
||||
IN ULONG IoFlags,
|
||||
IN ULONG AttributeFlags
|
||||
);
|
||||
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE,CmpOpenHiveFiles)
|
||||
#pragma alloc_text(PAGE,CmpInitializeHive)
|
||||
#pragma alloc_text(PAGE,CmpDestroyHive)
|
||||
#pragma alloc_text(PAGE,CmpOpenFileWithExtremePrejudice)
|
||||
#endif
|
||||
|
||||
extern PCMHIVE CmpMasterHive;
|
||||
extern LIST_ENTRY CmpHiveListHead;
|
||||
|
||||
NTSTATUS
|
||||
CmpOpenHiveFiles(
|
||||
PUNICODE_STRING BaseName,
|
||||
PWSTR Extension OPTIONAL,
|
||||
PHANDLE Primary,
|
||||
PHANDLE Secondary,
|
||||
PULONG PrimaryDisposition,
|
||||
PULONG SecondaryDisposition,
|
||||
BOOLEAN CreateAllowed,
|
||||
BOOLEAN MarkAsSystemHive,
|
||||
BOOLEAN NoBuffering,
|
||||
OUT OPTIONAL PULONG ClusterSize
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Open/Create Primary, and Log files for Hives.
|
||||
|
||||
BaseName is some name like "\winnt\system32\config\system".
|
||||
Extension is ".alt" or ".log" or NULL.
|
||||
|
||||
If extension is NULL skip secondary work.
|
||||
|
||||
If extension is .alt or .log, open/create a secondary file
|
||||
(e.g. "\winnt\system32\config\system.alt")
|
||||
|
||||
If extension is .log, open secondary for buffered I/O, else,
|
||||
open for non-buffered I/O. Primary always uses non-buffered I/O.
|
||||
|
||||
If primary is newly created, supersede secondary. If secondary
|
||||
does not exist, simply create (other code will complain if Log
|
||||
is needed but does not exist.)
|
||||
|
||||
WARNING: If Secondary handle is NULL, you have no log
|
||||
or alternate!
|
||||
|
||||
Arguments:
|
||||
|
||||
BaseName - unicode string of base hive file, must have space for
|
||||
extension if that is used.
|
||||
|
||||
Extension - unicode type extension of secondary file, including
|
||||
the leading "."
|
||||
|
||||
Primary - will get handle to primary file
|
||||
|
||||
Secondary - will get handle to secondary, or NULL
|
||||
|
||||
PrimaryDisposition - STATUS_SUCCESS or STATUS_CREATED, of primary file.
|
||||
|
||||
SecondaryDisposition - STATUS_SUCCESS or STATUS_CREATED, of secondary file.
|
||||
|
||||
CreateAllowed - if TRUE will create nonexistent primary, if FALSE will
|
||||
fail if primary does not exist. no effect on log
|
||||
|
||||
MarkAsSystemHive - if TRUE will call into file system to mark this
|
||||
as a critical system hive.
|
||||
|
||||
ClusterSize - if not NULL, will compute and return the appropriate
|
||||
cluster size for the primary file.
|
||||
|
||||
Return Value:
|
||||
|
||||
status - if status is success, Primary succeeded, check Secondary
|
||||
value to see if it succeeded.
|
||||
|
||||
--*/
|
||||
{
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
IO_STATUS_BLOCK FsctlIoStatus;
|
||||
FILE_FS_SIZE_INFORMATION FsSizeInformation;
|
||||
ULONG Cluster;
|
||||
ULONG CreateDisposition;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
NTSTATUS status;
|
||||
UNICODE_STRING ExtName;
|
||||
UNICODE_STRING WorkName;
|
||||
PVOID WorkBuffer;
|
||||
USHORT NameSize;
|
||||
ULONG IoFlags;
|
||||
ULONG AttributeFlags;
|
||||
ULONG ShareMode;
|
||||
ULONG DesiredAccess;
|
||||
USHORT CompressionState;
|
||||
HANDLE hEvent;
|
||||
PKEVENT pEvent;
|
||||
|
||||
//
|
||||
// Allocate an event to use for our overlapped I/O
|
||||
//
|
||||
status = CmpCreateEvent(NotificationEvent, &hEvent, &pEvent);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return(status);
|
||||
}
|
||||
|
||||
//
|
||||
// Allocate a buffer big enough to hold the full name
|
||||
//
|
||||
WorkName.Length = 0;
|
||||
WorkName.MaximumLength = 0;
|
||||
WorkName.Buffer = NULL;
|
||||
|
||||
NameSize = BaseName->Length;
|
||||
if (ARGUMENT_PRESENT(Extension)) {
|
||||
NameSize = (USHORT)(NameSize + (wcslen(Extension)+1) * sizeof(WCHAR));
|
||||
WorkBuffer = ExAllocatePool(PagedPool, NameSize);
|
||||
if (WorkBuffer == NULL) {
|
||||
ObDereferenceObject(pEvent);
|
||||
ZwClose(hEvent);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
WorkName.Buffer = WorkBuffer;
|
||||
WorkName.MaximumLength = NameSize;
|
||||
RtlAppendStringToString((PSTRING)&WorkName, (PSTRING)BaseName);
|
||||
} else {
|
||||
WorkName = *BaseName;
|
||||
WorkBuffer = NULL;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Open/Create the primary
|
||||
//
|
||||
InitializeObjectAttributes(
|
||||
&ObjectAttributes,
|
||||
&WorkName,
|
||||
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (CreateAllowed && !CmpShareSystemHives) {
|
||||
CreateDisposition = FILE_OPEN_IF;
|
||||
} else {
|
||||
CreateDisposition = FILE_OPEN;
|
||||
}
|
||||
|
||||
ASSERT_PASSIVE_LEVEL();
|
||||
|
||||
AttributeFlags = FILE_OPEN_FOR_BACKUP_INTENT | FILE_NO_COMPRESSION | FILE_RANDOM_ACCESS;
|
||||
if( NoBuffering == TRUE ) {
|
||||
AttributeFlags |= FILE_NO_INTERMEDIATE_BUFFERING;
|
||||
}
|
||||
|
||||
//
|
||||
// Share the file if needed
|
||||
//
|
||||
if (CmpMiniNTBoot && CmpShareSystemHives) {
|
||||
DesiredAccess = FILE_READ_DATA;
|
||||
ShareMode = FILE_SHARE_READ;
|
||||
} else {
|
||||
ShareMode = 0;
|
||||
DesiredAccess = FILE_READ_DATA | FILE_WRITE_DATA;
|
||||
}
|
||||
|
||||
status = ZwCreateFile(
|
||||
Primary,
|
||||
DesiredAccess,
|
||||
&ObjectAttributes,
|
||||
&IoStatus,
|
||||
NULL, // alloc size = none
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
ShareMode, // share nothing
|
||||
CreateDisposition,
|
||||
AttributeFlags,
|
||||
NULL, // eabuffer
|
||||
0 // ealength
|
||||
);
|
||||
|
||||
if (status == STATUS_ACCESS_DENIED) {
|
||||
|
||||
//
|
||||
// This means some person has put a read-only attribute
|
||||
// on one of the critical system hive files. Remove it so they
|
||||
// don't hurt themselves.
|
||||
//
|
||||
|
||||
status = CmpOpenFileWithExtremePrejudice(Primary,
|
||||
&ObjectAttributes,
|
||||
AttributeFlags,
|
||||
FILE_ATTRIBUTE_NORMAL);
|
||||
}
|
||||
|
||||
if (!CmpShareSystemHives && (MarkAsSystemHive) &&
|
||||
(NT_SUCCESS(status))) {
|
||||
|
||||
ASSERT_PASSIVE_LEVEL();
|
||||
status = ZwFsControlFile(*Primary,
|
||||
hEvent,
|
||||
NULL,
|
||||
NULL,
|
||||
&FsctlIoStatus,
|
||||
FSCTL_MARK_AS_SYSTEM_HIVE,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
0);
|
||||
if (status == STATUS_PENDING) {
|
||||
KeWaitForSingleObject(pEvent,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
status = FsctlIoStatus.Status;
|
||||
}
|
||||
|
||||
//
|
||||
// STATUS_INVALID_DEVICE_REQUEST is OK.
|
||||
//
|
||||
|
||||
if (status == STATUS_INVALID_DEVICE_REQUEST) {
|
||||
status = STATUS_SUCCESS;
|
||||
|
||||
} else if (!NT_SUCCESS(status)) {
|
||||
ZwClose(*Primary);
|
||||
}
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"CMINIT: CmpOpenHiveFile: "));
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"\tPrimary Open/Create failed for:\n"));
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"\t%wZ\n", &WorkName));
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"\tstatus = %08lx\n", status));
|
||||
|
||||
if (WorkBuffer != NULL) {
|
||||
ExFreePool(WorkBuffer);
|
||||
}
|
||||
ObDereferenceObject(pEvent);
|
||||
ZwClose(hEvent);
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Make sure the file is uncompressed in order to prevent the filesystem
|
||||
// from failing our updates due to disk full conditions.
|
||||
//
|
||||
// Do not fail to open the file if this fails, we don't want to prevent
|
||||
// people from booting just because their disk is full. Although they
|
||||
// will not be able to update their registry, they will at lease be
|
||||
// able to delete some files.
|
||||
//
|
||||
CompressionState = 0;
|
||||
ASSERT_PASSIVE_LEVEL();
|
||||
status = ZwFsControlFile(*Primary,
|
||||
hEvent,
|
||||
NULL,
|
||||
NULL,
|
||||
&FsctlIoStatus,
|
||||
FSCTL_SET_COMPRESSION,
|
||||
&CompressionState,
|
||||
sizeof(CompressionState),
|
||||
NULL,
|
||||
0);
|
||||
if (status == STATUS_PENDING) {
|
||||
KeWaitForSingleObject(pEvent,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
}
|
||||
|
||||
*PrimaryDisposition = (ULONG) IoStatus.Information;
|
||||
|
||||
if( *PrimaryDisposition != FILE_CREATED ) {
|
||||
//
|
||||
// 0-length file case
|
||||
//
|
||||
FILE_STANDARD_INFORMATION FileInformation;
|
||||
NTSTATUS status2;
|
||||
|
||||
status2 = ZwQueryInformationFile(*Primary,
|
||||
&IoStatus,
|
||||
(PVOID)&FileInformation,
|
||||
sizeof( FileInformation ),
|
||||
FileStandardInformation
|
||||
);
|
||||
if (NT_SUCCESS( status2 )) {
|
||||
if(FileInformation.EndOfFile.QuadPart == 0) {
|
||||
//
|
||||
// treat it as a non-existent one.
|
||||
//
|
||||
*PrimaryDisposition = FILE_CREATED;
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"Primary file is zero-length => treat it as non-existent\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ARGUMENT_PRESENT(ClusterSize)) {
|
||||
|
||||
ASSERT_PASSIVE_LEVEL();
|
||||
status = ZwQueryVolumeInformationFile(*Primary,
|
||||
&IoStatus,
|
||||
&FsSizeInformation,
|
||||
sizeof(FILE_FS_SIZE_INFORMATION),
|
||||
FileFsSizeInformation);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
ObDereferenceObject(pEvent);
|
||||
ZwClose(hEvent);
|
||||
return(status);
|
||||
}
|
||||
if (FsSizeInformation.BytesPerSector > HBLOCK_SIZE) {
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"CmpOpenHiveFiles: sectorsize %lx > HBLOCK_SIZE\n"));
|
||||
ObDereferenceObject(pEvent);
|
||||
ZwClose(hEvent);
|
||||
return(STATUS_CANNOT_LOAD_REGISTRY_FILE);
|
||||
}
|
||||
|
||||
Cluster = FsSizeInformation.BytesPerSector / HSECTOR_SIZE;
|
||||
*ClusterSize = (Cluster < 1) ? 1 : Cluster;
|
||||
|
||||
}
|
||||
|
||||
if ( ! ARGUMENT_PRESENT(Extension)) {
|
||||
if (WorkBuffer != NULL) {
|
||||
ExFreePool(WorkBuffer);
|
||||
}
|
||||
ObDereferenceObject(pEvent);
|
||||
ZwClose(hEvent);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Open/Create the secondary
|
||||
//
|
||||
CreateDisposition = CmpShareSystemHives ? FILE_OPEN : FILE_OPEN_IF;
|
||||
|
||||
if (*PrimaryDisposition == FILE_CREATED) {
|
||||
CreateDisposition = FILE_SUPERSEDE;
|
||||
}
|
||||
|
||||
RtlInitUnicodeString(&ExtName,Extension);
|
||||
status = RtlAppendStringToString((PSTRING)&WorkName, (PSTRING)&ExtName);
|
||||
|
||||
InitializeObjectAttributes(&ObjectAttributes,
|
||||
&WorkName,
|
||||
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
//
|
||||
// non-cached log files (or alternates)
|
||||
//
|
||||
IoFlags = FILE_NO_COMPRESSION | FILE_NO_INTERMEDIATE_BUFFERING;
|
||||
if (_wcsnicmp(Extension, L".log", 4) != 0) {
|
||||
AttributeFlags = FILE_ATTRIBUTE_NORMAL;
|
||||
} else {
|
||||
AttributeFlags = FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_HIDDEN;
|
||||
}
|
||||
|
||||
ASSERT_PASSIVE_LEVEL();
|
||||
status = ZwCreateFile(
|
||||
Secondary,
|
||||
DesiredAccess,
|
||||
&ObjectAttributes,
|
||||
&IoStatus,
|
||||
NULL, // alloc size = none
|
||||
AttributeFlags,
|
||||
ShareMode,
|
||||
CreateDisposition,
|
||||
IoFlags,
|
||||
NULL, // eabuffer
|
||||
0 // ealength
|
||||
);
|
||||
|
||||
if (status == STATUS_ACCESS_DENIED) {
|
||||
|
||||
//
|
||||
// This means some person has put a read-only attribute
|
||||
// on one of the critical system hive files. Remove it so they
|
||||
// don't hurt themselves.
|
||||
//
|
||||
|
||||
status = CmpOpenFileWithExtremePrejudice(Secondary,
|
||||
&ObjectAttributes,
|
||||
IoFlags,
|
||||
AttributeFlags);
|
||||
}
|
||||
|
||||
if (!CmpShareSystemHives && (MarkAsSystemHive) &&
|
||||
(NT_SUCCESS(status))) {
|
||||
|
||||
ASSERT_PASSIVE_LEVEL();
|
||||
status = ZwFsControlFile(*Secondary,
|
||||
hEvent,
|
||||
NULL,
|
||||
NULL,
|
||||
&FsctlIoStatus,
|
||||
FSCTL_MARK_AS_SYSTEM_HIVE,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
0);
|
||||
if (status == STATUS_PENDING) {
|
||||
KeWaitForSingleObject(pEvent,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
status = FsctlIoStatus.Status;
|
||||
}
|
||||
//
|
||||
// STATUS_INVALID_DEVICE_REQUEST is OK.
|
||||
//
|
||||
|
||||
if (status == STATUS_INVALID_DEVICE_REQUEST) {
|
||||
status = STATUS_SUCCESS;
|
||||
|
||||
} else if (!NT_SUCCESS(status)) {
|
||||
|
||||
ZwClose(*Secondary);
|
||||
}
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"CMINIT: CmpOpenHiveFile: "));
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"\tSecondary Open/Create failed for:\n"));
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"\t%wZ\n", &WorkName));
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"\tstatus = %08lx\n", status));
|
||||
|
||||
*Secondary = NULL;
|
||||
} else {
|
||||
*SecondaryDisposition = (ULONG) IoStatus.Information;
|
||||
|
||||
//
|
||||
// Make sure the file is uncompressed in order to prevent the filesystem
|
||||
// from failing our updates due to disk full conditions.
|
||||
//
|
||||
// Do not fail to open the file if this fails, we don't want to prevent
|
||||
// people from booting just because their disk is full. Although they
|
||||
// will not be able to update their registry, they will at least be
|
||||
// able to delete some files.
|
||||
//
|
||||
CompressionState = 0;
|
||||
|
||||
ASSERT_PASSIVE_LEVEL();
|
||||
status = ZwFsControlFile(*Secondary,
|
||||
hEvent,
|
||||
NULL,
|
||||
NULL,
|
||||
&FsctlIoStatus,
|
||||
FSCTL_SET_COMPRESSION,
|
||||
&CompressionState,
|
||||
sizeof(CompressionState),
|
||||
NULL,
|
||||
0);
|
||||
if (status == STATUS_PENDING) {
|
||||
KeWaitForSingleObject(pEvent,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (WorkBuffer != NULL) {
|
||||
ExFreePool(WorkBuffer);
|
||||
}
|
||||
ObDereferenceObject(pEvent);
|
||||
ZwClose(hEvent);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
CmpInitializeHive(
|
||||
PCMHIVE *CmHive,
|
||||
ULONG OperationType,
|
||||
ULONG HiveFlags,
|
||||
ULONG FileType,
|
||||
PVOID HiveData OPTIONAL,
|
||||
HANDLE Primary,
|
||||
HANDLE Log,
|
||||
HANDLE External,
|
||||
PUNICODE_STRING FileName OPTIONAL,
|
||||
ULONG CheckFlags
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Initialize a hive.
|
||||
|
||||
Arguments:
|
||||
|
||||
CmHive - pointer to a variable to receive a pointer to the CmHive structure
|
||||
|
||||
OperationType - specifies whether to create a new hive from scratch,
|
||||
from a memory image, or by reading a file from disk.
|
||||
[HINIT_CREATE | HINIT_MEMORY | HINIT_FILE | HINIT_MAPFILE]
|
||||
|
||||
HiveFlags - HIVE_VOLATILE - Entire hive is to be volatile, regardless
|
||||
of the types of cells allocated
|
||||
HIVE_NO_LAZY_FLUSH - Data in this hive is never written
|
||||
to disk except by an explicit FlushKey
|
||||
|
||||
FileType - HFILE_TYPE_*, HFILE_TYPE_LOG set up for logging support
|
||||
|
||||
HiveData - if present, supplies a pointer to an in memory image of
|
||||
from which to init the hive. Only useful when OperationType
|
||||
is set to HINIT_MEMORY.
|
||||
|
||||
Primary - File handle for primary hive file (e.g. SYSTEM)
|
||||
|
||||
Log - File handle for log hive file (e.g. SOFTWARE.LOG)
|
||||
|
||||
External - File handle for primary hive file (e.g. BACKUP.REG)
|
||||
|
||||
FileName - some path like "...\system32\config\system", which will
|
||||
be written into the base block as an aid to debugging.
|
||||
may be NULL.
|
||||
|
||||
CheckFlags - Flags to be passed to CmCheckRegistry
|
||||
|
||||
usually this is CM_CHECK_REGISTRY_CHECK_CLEAN, except for the system hive
|
||||
where CM_CHECK_REGISTRY_FORCE_CLEAN is passed
|
||||
|
||||
Return Value:
|
||||
|
||||
NTSTATUS
|
||||
|
||||
--*/
|
||||
{
|
||||
FILE_FS_SIZE_INFORMATION FsSizeInformation;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
ULONG Cluster;
|
||||
NTSTATUS Status;
|
||||
PCMHIVE cmhive2;
|
||||
ULONG rc;
|
||||
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_INIT,"CmpInitializeHive:\t\n"));
|
||||
|
||||
//
|
||||
// Reject illegal parms
|
||||
//
|
||||
if ( (External && (Primary || Log)) ||
|
||||
(Log && !Primary) ||
|
||||
(!CmpShareSystemHives && (HiveFlags & HIVE_VOLATILE) && (Primary || External || Log)) ||
|
||||
((OperationType == HINIT_MEMORY) && (!ARGUMENT_PRESENT(HiveData))) ||
|
||||
(Log && (FileType != HFILE_TYPE_LOG))
|
||||
)
|
||||
{
|
||||
return (STATUS_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
//
|
||||
// compute control
|
||||
//
|
||||
if (Primary) {
|
||||
|
||||
ASSERT_PASSIVE_LEVEL();
|
||||
Status = ZwQueryVolumeInformationFile(
|
||||
Primary,
|
||||
&IoStatusBlock,
|
||||
&FsSizeInformation,
|
||||
sizeof(FILE_FS_SIZE_INFORMATION),
|
||||
FileFsSizeInformation
|
||||
);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
return (Status);
|
||||
}
|
||||
if (FsSizeInformation.BytesPerSector > HBLOCK_SIZE) {
|
||||
return (STATUS_REGISTRY_IO_FAILED);
|
||||
}
|
||||
Cluster = FsSizeInformation.BytesPerSector / HSECTOR_SIZE;
|
||||
Cluster = (Cluster < 1) ? 1 : Cluster;
|
||||
} else {
|
||||
Cluster = 1;
|
||||
}
|
||||
|
||||
cmhive2 = CmpAllocate(sizeof(CMHIVE), FALSE,CM_FIND_LEAK_TAG10);
|
||||
|
||||
if (cmhive2 == NULL) {
|
||||
return (STATUS_INSUFFICIENT_RESOURCES);
|
||||
}
|
||||
|
||||
cmhive2->UnloadEvent = NULL;
|
||||
cmhive2->RootKcb = NULL;
|
||||
cmhive2->Frozen = FALSE;
|
||||
cmhive2->UnloadWorkItem = NULL;
|
||||
|
||||
cmhive2->GrowOnlyMode = FALSE;
|
||||
cmhive2->GrowOffset = 0;
|
||||
#if DBG
|
||||
cmhive2->HiveIsLoading = TRUE;
|
||||
#endif
|
||||
cmhive2->CreatorOwner = NULL;
|
||||
|
||||
InitializeListHead(&(cmhive2->KcbConvertListHead));
|
||||
InitializeListHead(&(cmhive2->KnodeConvertListHead));
|
||||
cmhive2->CellRemapArray = NULL;
|
||||
|
||||
//
|
||||
// Allocate the mutex from NonPagedPool so it will not be swapped to the disk
|
||||
//
|
||||
cmhive2->ViewLock = (PKGUARDED_MUTEX)ExAllocatePoolWithTag(NonPagedPool, sizeof(KGUARDED_MUTEX), CM_POOL_TAG );
|
||||
if( cmhive2->ViewLock == NULL ) {
|
||||
CmpFree(cmhive2, sizeof(CMHIVE));
|
||||
return (STATUS_INSUFFICIENT_RESOURCES);
|
||||
}
|
||||
|
||||
#if DBG
|
||||
cmhive2->FlusherLock = (PERESOURCE)ExAllocatePoolWithTag(NonPagedPool, sizeof(ERESOURCE), CM_POOL_TAG );
|
||||
if( cmhive2->FlusherLock == NULL ) {
|
||||
CmpFreeMutex(cmhive2->ViewLock);
|
||||
CmpFree(cmhive2, sizeof(CMHIVE));
|
||||
return (STATUS_INSUFFICIENT_RESOURCES);
|
||||
}
|
||||
#endif
|
||||
|
||||
// need to do this consistently!!!
|
||||
cmhive2->FileObject = NULL;
|
||||
cmhive2->FileFullPath.Buffer = NULL;
|
||||
cmhive2->FileFullPath.Length = 0;
|
||||
cmhive2->FileFullPath.MaximumLength = 0;
|
||||
|
||||
cmhive2->FileUserName.Buffer = NULL;
|
||||
cmhive2->FileUserName.Length = 0;
|
||||
cmhive2->FileUserName.MaximumLength = 0;
|
||||
|
||||
//
|
||||
// Initialize the Cm hive control block
|
||||
//
|
||||
//
|
||||
ASSERT((HFILE_TYPE_EXTERNAL+1) == HFILE_TYPE_MAX);
|
||||
cmhive2->FileHandles[HFILE_TYPE_PRIMARY] = Primary;
|
||||
cmhive2->FileHandles[HFILE_TYPE_LOG] = Log;
|
||||
cmhive2->FileHandles[HFILE_TYPE_EXTERNAL] = External;
|
||||
|
||||
cmhive2->NotifyList.Flink = NULL;
|
||||
cmhive2->NotifyList.Blink = NULL;
|
||||
|
||||
ExInitializePushLock(&(cmhive2->HiveLock));
|
||||
|
||||
#if DBG
|
||||
cmhive2->HiveLockOwner = NULL;
|
||||
KeInitializeGuardedMutex(cmhive2->ViewLock);
|
||||
cmhive2->ViewLockOwner = NULL;
|
||||
ExInitializePushLock(&(cmhive2->WriterLock));
|
||||
cmhive2->WriterLockOwner = NULL;
|
||||
ExInitializeResourceLite(cmhive2->FlusherLock);
|
||||
ExInitializePushLock(&(cmhive2->SecurityLock));
|
||||
cmhive2->HiveSecurityLockOwner = NULL;
|
||||
#else
|
||||
KeInitializeGuardedMutex(cmhive2->ViewLock);
|
||||
ExInitializePushLock(&(cmhive2->WriterLock));
|
||||
ExInitializePushLock(&(cmhive2->FlusherLock));
|
||||
ExInitializePushLock(&(cmhive2->SecurityLock));
|
||||
#endif
|
||||
|
||||
CmpInitHiveViewList(cmhive2);
|
||||
cmhive2->Flags = 0;
|
||||
InitializeListHead(&(cmhive2->TrustClassEntry));
|
||||
cmhive2->FlushCount = 0;
|
||||
//
|
||||
// Initialize the view list
|
||||
//
|
||||
#if DBG
|
||||
if( FileName ) {
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"Initializing HiveViewList for hive (%p) (%.*S) \n\n",cmhive2,FileName->Length / sizeof(WCHAR),FileName->Buffer));
|
||||
}
|
||||
#endif
|
||||
|
||||
//
|
||||
// Initialize the security cache
|
||||
//
|
||||
CmpInitSecurityCache(cmhive2);
|
||||
|
||||
//
|
||||
// Initialize the Hv hive control block
|
||||
//
|
||||
Status = HvInitializeHive(
|
||||
&(cmhive2->Hive),
|
||||
OperationType,
|
||||
HiveFlags,
|
||||
FileType,
|
||||
HiveData,
|
||||
CmpAllocate,
|
||||
CmpFree,
|
||||
CmpFileSetSize,
|
||||
CmpFileWrite,
|
||||
CmpFileRead,
|
||||
CmpFileFlush,
|
||||
Cluster,
|
||||
FileName
|
||||
);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"CmpInitializeHive: "));
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"HvInitializeHive failed, Status = %08lx\n", Status));
|
||||
|
||||
if( !(cmhive2->Hive.HiveFlags & HIVE_HAS_BEEN_FREED) ) {
|
||||
HvpFreeHiveFreeDisplay((PHHIVE)cmhive2);
|
||||
HvpCleanMap((PHHIVE)cmhive2);
|
||||
}
|
||||
|
||||
CmpFreeMutex(cmhive2->ViewLock);
|
||||
#if DBG
|
||||
CmpFreeResource(cmhive2->FlusherLock);
|
||||
#endif
|
||||
CmpDestroyHiveViewList(cmhive2);
|
||||
CmpDestroySecurityCache (cmhive2);
|
||||
CmpDropFileObjectForHive(cmhive2);
|
||||
CmpUnJoinClassOfTrust(cmhive2);
|
||||
|
||||
CmpCheckForOrphanedKcbs((PHHIVE)cmhive2);
|
||||
|
||||
CmpFree(cmhive2, sizeof(CMHIVE));
|
||||
return (Status);
|
||||
|
||||
|
||||
}
|
||||
if ( (OperationType == HINIT_FILE) ||
|
||||
(OperationType == HINIT_MAPFILE) ||
|
||||
(OperationType == HINIT_MEMORY) ||
|
||||
(OperationType == HINIT_MEMORY_INPLACE))
|
||||
{
|
||||
|
||||
rc = CmCheckRegistry(cmhive2, CheckFlags);
|
||||
if (rc != 0) {
|
||||
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"CmpInitializeHive: "));
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_BUGCHECK,"CmCheckRegistry failed, rc = %08lx\n",rc));
|
||||
//
|
||||
// we have dirtied some cells (by clearing the volatile information)
|
||||
// we need first to unpin all the views
|
||||
|
||||
CmpDestroyHiveViewList(cmhive2);
|
||||
CmpDestroySecurityCache(cmhive2);
|
||||
CmpDropFileObjectForHive(cmhive2);
|
||||
CmpUnJoinClassOfTrust(cmhive2);
|
||||
|
||||
CmpCheckForOrphanedKcbs((PHHIVE)cmhive2);
|
||||
HvFreeHive((PHHIVE)cmhive2);
|
||||
|
||||
CmpFreeMutex(cmhive2->ViewLock);
|
||||
#if DBG
|
||||
CmpFreeResource(cmhive2->FlusherLock);
|
||||
#endif
|
||||
CmpFree(cmhive2, sizeof(CMHIVE));
|
||||
return(STATUS_REGISTRY_CORRUPT);
|
||||
}
|
||||
}
|
||||
|
||||
#if DBG
|
||||
cmhive2->HiveIsLoading = FALSE;
|
||||
#endif
|
||||
if( !(CheckFlags&CM_DONT_ADD_TO_HIVE_LIST) ) {
|
||||
CmpLockHiveListExclusive(); // at the end so system hive is first during the lazy flush iteration
|
||||
InsertTailList(&CmpHiveListHead, &(cmhive2->HiveList));
|
||||
CmpUnlockHiveList();
|
||||
}
|
||||
*CmHive = cmhive2;
|
||||
return (STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
LOGICAL
|
||||
CmpDestroyHive(
|
||||
IN PHHIVE Hive,
|
||||
IN HCELL_INDEX Cell
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine tears down a cmhive.
|
||||
|
||||
Arguments:
|
||||
|
||||
Hive - Supplies a pointer to the hive to be freed.
|
||||
|
||||
Cell - Supplies index of the hive's root cell.
|
||||
|
||||
Return Value:
|
||||
|
||||
TRUE if successful
|
||||
FALSE if some failure occurred
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
PCELL_DATA CellData;
|
||||
HCELL_INDEX LinkCell;
|
||||
NTSTATUS Status;
|
||||
|
||||
//
|
||||
// First find the link cell.
|
||||
//
|
||||
CellData = HvGetCell(Hive, Cell);
|
||||
if( CellData == NULL ) {
|
||||
//
|
||||
// we couldn't map the bin containing this cell
|
||||
//
|
||||
return FALSE;
|
||||
}
|
||||
LinkCell = CellData->u.KeyNode.Parent;
|
||||
HvReleaseCell(Hive, Cell);
|
||||
|
||||
//
|
||||
// Now delete the link cell.
|
||||
//
|
||||
ASSERT(FIELD_OFFSET(CMHIVE, Hive) == 0);
|
||||
CmpLockHiveFlusherExclusive(CmpMasterHive);
|
||||
Status = CmpFreeKeyByCell((PHHIVE)CmpMasterHive, LinkCell, TRUE);
|
||||
CmpUnlockHiveFlusher(CmpMasterHive);
|
||||
|
||||
if (NT_SUCCESS(Status)) {
|
||||
//
|
||||
// Take the hive out of the hive list
|
||||
//
|
||||
CmpLockHiveListExclusive();
|
||||
CmpRemoveEntryList(&( ((PCMHIVE)Hive)->HiveList));
|
||||
CmpUnlockHiveList();
|
||||
return(TRUE);
|
||||
} else {
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
CmpOpenFileWithExtremePrejudice(
|
||||
OUT PHANDLE Primary,
|
||||
IN POBJECT_ATTRIBUTES Obja,
|
||||
IN ULONG IoFlags,
|
||||
IN ULONG AttributeFlags
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine opens a hive file that some person has put a
|
||||
read-only attribute on. It is used to prevent people from hurting
|
||||
themselves by making the critical system hive files read-only.
|
||||
|
||||
Arguments:
|
||||
|
||||
Primary - Returns handle to file
|
||||
|
||||
Obja - Supplies Object Attributes of file.
|
||||
|
||||
IoFlags - Supplies flags to pass to ZwCreateFile
|
||||
|
||||
Return Value:
|
||||
|
||||
NTSTATUS
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
NTSTATUS Status;
|
||||
HANDLE Handle;
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
FILE_BASIC_INFORMATION FileInfo;
|
||||
|
||||
RtlZeroMemory(&FileInfo, sizeof(FileInfo));
|
||||
//
|
||||
// Get the current file attributes
|
||||
//
|
||||
ASSERT_PASSIVE_LEVEL();
|
||||
Status = ZwQueryAttributesFile(Obja, &FileInfo);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"ZwQueryAttributesFile failed with IO status %lx\n",Status));
|
||||
return(Status);
|
||||
}
|
||||
|
||||
//
|
||||
// Clear the readonly bit.
|
||||
//
|
||||
FileInfo.FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
|
||||
|
||||
//
|
||||
// Open the file
|
||||
//
|
||||
Status = ZwOpenFile(&Handle,
|
||||
FILE_WRITE_ATTRIBUTES,
|
||||
Obja,
|
||||
&IoStatusBlock,
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
FILE_OPEN_FOR_BACKUP_INTENT);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
return(Status);
|
||||
}
|
||||
|
||||
//
|
||||
// Set the new attributes
|
||||
//
|
||||
Status = ZwSetInformationFile(Handle,
|
||||
&IoStatusBlock,
|
||||
&FileInfo,
|
||||
sizeof(FileInfo),
|
||||
FileBasicInformation);
|
||||
ZwClose(Handle);
|
||||
if (NT_SUCCESS(Status)) {
|
||||
//
|
||||
// Reopen the file with the access that we really need.
|
||||
//
|
||||
Status = ZwCreateFile(Primary,
|
||||
FILE_READ_DATA | FILE_WRITE_DATA,
|
||||
Obja,
|
||||
&IoStatusBlock,
|
||||
NULL,
|
||||
AttributeFlags,
|
||||
0,
|
||||
FILE_OPEN,
|
||||
IoFlags,
|
||||
NULL,
|
||||
0);
|
||||
}
|
||||
#if DBG
|
||||
else {
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"ZwSetInformationFile failed with IO status %lx\n",Status));
|
||||
}
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,DPFLTR_ERROR_LEVEL,"CmpOpenFileWithExtremePrejudice returns with IO status %lx\n",Status));
|
||||
#endif
|
||||
|
||||
return(Status);
|
||||
|
||||
}
|
||||
2026
base/ntos/config/cmmapvw.c
Normal file
2026
base/ntos/config/cmmapvw.c
Normal file
File diff suppressed because it is too large
Load Diff
397
base/ntos/config/cmname.c
Normal file
397
base/ntos/config/cmname.c
Normal file
@ -0,0 +1,397 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
cmname.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Provides routines for handling name comparisons and converting to/from the registry
|
||||
compressed name format.
|
||||
|
||||
--*/
|
||||
|
||||
#include "cmp.h"
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE,CmpNameSize)
|
||||
#pragma alloc_text(PAGE,CmpCopyName)
|
||||
#pragma alloc_text(PAGE,CmpCompressedNameSize)
|
||||
#pragma alloc_text(PAGE,CmpCopyCompressedName)
|
||||
#pragma alloc_text(PAGE,CmpCompareCompressedName)
|
||||
#pragma alloc_text(PAGE,CmpCompareUnicodeString)
|
||||
#pragma alloc_text(PAGE,CmpCompareTwoCompressedNames)
|
||||
#endif
|
||||
|
||||
|
||||
USHORT
|
||||
CmpNameSize(
|
||||
IN PHHIVE Hive,
|
||||
IN PUNICODE_STRING Name
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Determines the space needed to store a given string in the registry. May apply
|
||||
any relevant compression to compute the length, but the compression used is
|
||||
guaranteed to be the same as CmpCopyName.
|
||||
|
||||
Arguments:
|
||||
|
||||
Hive - supplies the hive control structure (for version checking)
|
||||
|
||||
Name - Supplies the unicode string to be copied into the registry.
|
||||
|
||||
Return Value:
|
||||
|
||||
The number of bytes of storage required to store this name.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
if (Hive->Version == 1) {
|
||||
return(Name->Length);
|
||||
}
|
||||
for (i=0;i<Name->Length/sizeof(WCHAR);i++) {
|
||||
if ((USHORT)Name->Buffer[i] > (UCHAR)-1) {
|
||||
return(Name->Length);
|
||||
}
|
||||
}
|
||||
return(Name->Length / sizeof(WCHAR));
|
||||
|
||||
}
|
||||
|
||||
USHORT
|
||||
CmpCopyName(
|
||||
IN PHHIVE Hive,
|
||||
IN PWCHAR Destination,
|
||||
IN PUNICODE_STRING Source
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Copies the given unicode name into the registry, applying any relevant compression
|
||||
at the same time.
|
||||
|
||||
Arguments:
|
||||
|
||||
Hive - supplies the hive control structure (For version checking)
|
||||
|
||||
Destination - Supplies the destination of the given string.
|
||||
|
||||
Source - Supplies the unicode string to copy into the registry.
|
||||
|
||||
Return Value:
|
||||
|
||||
Number of bytes of storage copied
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
if (Hive->Version==1) {
|
||||
RtlCopyMemory(Destination,Source->Buffer, Source->Length);
|
||||
return(Source->Length);
|
||||
}
|
||||
|
||||
for (i=0;i<Source->Length/sizeof(WCHAR);i++) {
|
||||
if ((USHORT)Source->Buffer[i] > (UCHAR)-1) {
|
||||
RtlCopyMemory(Destination,Source->Buffer, Source->Length);
|
||||
return(Source->Length);
|
||||
}
|
||||
((PUCHAR)Destination)[i] = (UCHAR)(Source->Buffer[i]);
|
||||
}
|
||||
return(Source->Length / sizeof(WCHAR));
|
||||
}
|
||||
|
||||
|
||||
USHORT
|
||||
CmpCompressedNameSize(
|
||||
IN PWCHAR Name,
|
||||
IN ULONG Length
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Computes the length of the unicode string that the given compressed name
|
||||
expands into.
|
||||
|
||||
Arguments:
|
||||
|
||||
Name - Supplies the compressed name.
|
||||
|
||||
Length - Supplies the length in bytes of the compressed name
|
||||
|
||||
Return Value:
|
||||
|
||||
The number of bytes of storage required to hold the Unicode expanded name.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
UNREFERENCED_PARAMETER (Name);
|
||||
|
||||
return((USHORT)Length*sizeof(WCHAR));
|
||||
}
|
||||
|
||||
|
||||
VOID
|
||||
CmpCopyCompressedName(
|
||||
IN PWCHAR Destination,
|
||||
IN ULONG DestinationLength,
|
||||
IN PWCHAR Source,
|
||||
IN ULONG SourceLength
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Copies a compressed name from the registry and expands it to Unicode.
|
||||
|
||||
Arguments:
|
||||
|
||||
Destination - Supplies the destination Unicode buffer
|
||||
|
||||
DestinationLength - Supplies the max length of the destination buffer in bytes
|
||||
|
||||
Source - Supplies the compressed string.
|
||||
|
||||
SourceLength - Supplies the length of the compressed string in bytes
|
||||
|
||||
Return Value:
|
||||
|
||||
None.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
ULONG i;
|
||||
ULONG Chars;
|
||||
|
||||
Chars = (DestinationLength/sizeof(WCHAR) < SourceLength)
|
||||
? DestinationLength/sizeof(WCHAR)
|
||||
: SourceLength;
|
||||
|
||||
for (i=0;i<Chars;i++) {
|
||||
Destination[i] = (WCHAR)(((PUCHAR)Source)[i]);
|
||||
}
|
||||
}
|
||||
|
||||
LONG
|
||||
CmpCompareCompressedName(
|
||||
IN PUNICODE_STRING SearchName,
|
||||
IN PWCHAR CompressedName,
|
||||
IN ULONG NameLength,
|
||||
IN ULONG CompareFlags
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Compares a compressed registry string to a Unicode string. Does a case-insensitive
|
||||
comparison.
|
||||
|
||||
Arguments:
|
||||
|
||||
SearchName - Supplies the Unicode string to be compared
|
||||
|
||||
CompressedName - Supplies the compressed string to be compared
|
||||
|
||||
NameLength - Supplies the length of the compressed string
|
||||
|
||||
Return Value:
|
||||
|
||||
0 = SearchName == CompressedName (of Cell)
|
||||
|
||||
< 0 = SearchName < CompressedName
|
||||
|
||||
> 0 = SearchName > CompressedName
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
WCHAR *s1;
|
||||
UCHAR *s2;
|
||||
USHORT n1, n2;
|
||||
WCHAR c1;
|
||||
WCHAR c2;
|
||||
LONG cDiff;
|
||||
|
||||
s1 = SearchName->Buffer;
|
||||
s2 = (UCHAR *)CompressedName;
|
||||
n1 = (USHORT )(SearchName->Length / sizeof(WCHAR));
|
||||
n2 = (USHORT )(NameLength);
|
||||
while (n1 && n2) {
|
||||
c1 = *s1++;
|
||||
c2 = (WCHAR)(*s2++);
|
||||
|
||||
//
|
||||
// there is a 2/3 chance they match without doing the uppercase comparison.
|
||||
//
|
||||
if( c1 != c2 ) {
|
||||
c1 = (CompareFlags&CMP_SOURCE_UP)?c1:CmUpcaseUnicodeChar(c1);
|
||||
c2 = (CompareFlags&CMP_DEST_UP)?c2:CmUpcaseUnicodeChar(c2);
|
||||
|
||||
if ((cDiff = ((LONG)c1 - (LONG)c2)) != 0) {
|
||||
return( cDiff );
|
||||
}
|
||||
}
|
||||
|
||||
n1--;
|
||||
n2--;
|
||||
}
|
||||
|
||||
return( n1 - n2 );
|
||||
}
|
||||
|
||||
|
||||
LONG
|
||||
CmpCompareUnicodeString(
|
||||
IN PUNICODE_STRING SourceName,
|
||||
IN PUNICODE_STRING DestName,
|
||||
IN ULONG CompareFlags
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Compares 2 unicode strings; Case insensitive comparison.
|
||||
Uses flags to avoid UpCasing strings again.
|
||||
|
||||
|
||||
Arguments:
|
||||
|
||||
SourceName - Supplies the Unicode string to be compared
|
||||
|
||||
DestName - Supplies the compressed string to be compared
|
||||
|
||||
CompareFlags - Supplies the flags to control comparison (see cmp.h)
|
||||
|
||||
Return Value:
|
||||
|
||||
0 = SearchName == CompressedName (of Cell)
|
||||
|
||||
< 0 = SearchName < CompressedName
|
||||
|
||||
> 0 = SearchName > CompressedName
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
WCHAR *s1, *s2;
|
||||
USHORT n1, n2;
|
||||
WCHAR c1, c2;
|
||||
LONG cDiff;
|
||||
|
||||
s1 = SourceName->Buffer;
|
||||
s2 = DestName->Buffer;
|
||||
n1 = (USHORT )(SourceName->Length / sizeof(WCHAR));
|
||||
n2 = (USHORT )(DestName->Length / sizeof(WCHAR));
|
||||
while (n1 && n2) {
|
||||
c1 = *s1++;
|
||||
c2 = *s2++;
|
||||
|
||||
//
|
||||
// there is a 2/3 chance of being the same case
|
||||
//
|
||||
if( c1 != c2 ){
|
||||
c1 = (CompareFlags&CMP_SOURCE_UP)?c1:CmUpcaseUnicodeChar(c1);
|
||||
c2 = (CompareFlags&CMP_DEST_UP)?c2:CmUpcaseUnicodeChar(c2);
|
||||
|
||||
if ((cDiff = ((LONG)c1 - (LONG)c2)) != 0) {
|
||||
return( cDiff );
|
||||
}
|
||||
}
|
||||
n1--;
|
||||
n2--;
|
||||
}
|
||||
|
||||
return( n1 - n2 );
|
||||
}
|
||||
|
||||
LONG
|
||||
CmpCompareTwoCompressedNames(
|
||||
IN PWCHAR CompressedName1,
|
||||
IN ULONG NameLength1,
|
||||
IN PWCHAR CompressedName2,
|
||||
IN ULONG NameLength2
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Compares 2 compressed registry strings. Does a case-insensitive
|
||||
comparison.
|
||||
|
||||
Arguments:
|
||||
|
||||
CompressedName1 - Supplies the compressed string to be compared
|
||||
|
||||
NameLength2 - Supplies the length of the compressed string
|
||||
|
||||
CompressedName1 - Supplies the compressed string to be compared
|
||||
|
||||
NameLength2 - Supplies the length of the compressed string
|
||||
|
||||
Return Value:
|
||||
|
||||
0 = CompressedName1 == CompressedName2 (of Cell)
|
||||
|
||||
< 0 = CompressedName1 < CompressedName2
|
||||
|
||||
> 0 = CompressedName1 > CompressedName2
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
UCHAR *s1;
|
||||
UCHAR *s2;
|
||||
USHORT n1, n2;
|
||||
WCHAR c1;
|
||||
WCHAR c2;
|
||||
LONG cDiff;
|
||||
|
||||
s1 = (UCHAR *)CompressedName1;
|
||||
s2 = (UCHAR *)CompressedName2;
|
||||
n1 = (USHORT )(NameLength1);
|
||||
n2 = (USHORT )(NameLength2);
|
||||
while (n1 && n2) {
|
||||
c1 = (WCHAR)(*s1++);
|
||||
c2 = (WCHAR)(*s2++);
|
||||
|
||||
//
|
||||
// there is a 2/3 chance they match without doing the upercpase comparison.
|
||||
//
|
||||
if( c1 != c2 ) {
|
||||
c1 = CmUpcaseUnicodeChar(c1);
|
||||
c2 = CmUpcaseUnicodeChar(c2);
|
||||
|
||||
if ((cDiff = ((LONG)c1 - (LONG)c2)) != 0) {
|
||||
return( cDiff );
|
||||
}
|
||||
}
|
||||
|
||||
n1--;
|
||||
n2--;
|
||||
}
|
||||
|
||||
return( n1 - n2 );
|
||||
}
|
||||
1933
base/ntos/config/cmnotify.c
Normal file
1933
base/ntos/config/cmnotify.c
Normal file
File diff suppressed because it is too large
Load Diff
2988
base/ntos/config/cmp.h
Normal file
2988
base/ntos/config/cmp.h
Normal file
File diff suppressed because it is too large
Load Diff
3449
base/ntos/config/cmparse.c
Normal file
3449
base/ntos/config/cmparse.c
Normal file
File diff suppressed because it is too large
Load Diff
761
base/ntos/config/cmparse2.c
Normal file
761
base/ntos/config/cmparse2.c
Normal file
@ -0,0 +1,761 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
cmparse2.c
|
||||
|
||||
Abstract:
|
||||
|
||||
This module contains parse routines for the configuration manager, particularly
|
||||
the registry.
|
||||
|
||||
--*/
|
||||
|
||||
#include "cmp.h"
|
||||
|
||||
BOOLEAN
|
||||
CmpOKToFollowLink( IN PCMHIVE OrigHive,
|
||||
IN PCMHIVE DestHive
|
||||
);
|
||||
|
||||
ULONG
|
||||
CmpUnLockKcbArray(IN PULONG LockedKcbs,
|
||||
IN ULONG Exempt);
|
||||
|
||||
VOID
|
||||
CmpReLockKcbArray(IN PULONG LockedKcbs,
|
||||
IN BOOLEAN LockExclusive);
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE,CmpDoCreate)
|
||||
#pragma alloc_text(PAGE,CmpDoCreateChild)
|
||||
#endif
|
||||
|
||||
extern PCM_KEY_CONTROL_BLOCK CmpKeyControlBlockRoot;
|
||||
|
||||
|
||||
NTSTATUS
|
||||
CmpDoCreate(
|
||||
IN PHHIVE Hive,
|
||||
IN HCELL_INDEX Cell,
|
||||
IN PACCESS_STATE AccessState,
|
||||
IN PUNICODE_STRING Name,
|
||||
IN KPROCESSOR_MODE AccessMode,
|
||||
IN PCM_PARSE_CONTEXT Context,
|
||||
IN PCM_KEY_CONTROL_BLOCK ParentKcb,
|
||||
IN PCMHIVE OriginatingHive OPTIONAL,
|
||||
OUT PVOID *Object
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Performs the first step in the creation of a registry key. This
|
||||
routine checks to make sure the caller has the proper access to
|
||||
create a key here, and allocates space for the child in the parent
|
||||
cell. It then calls CmpDoCreateChild to initialize the key and
|
||||
create the key object.
|
||||
|
||||
This two phase creation allows us to share the child creation code
|
||||
with the creation of link nodes.
|
||||
|
||||
Arguments:
|
||||
|
||||
Hive - supplies a pointer to the hive control structure for the hive
|
||||
|
||||
Cell - supplies index of node to create child under.
|
||||
|
||||
AccessState - Running security access state information for operation.
|
||||
|
||||
Name - supplies pointer to a UNICODE string which is the name of
|
||||
the child to be created.
|
||||
|
||||
AccessMode - Access mode of the original caller.
|
||||
|
||||
Context - pointer to CM_PARSE_CONTEXT structure passed through
|
||||
the object manager
|
||||
|
||||
BaseName - Name of object create is relative to
|
||||
|
||||
KeyName - Relative name (to BaseName)
|
||||
|
||||
Object - The address of a variable to receive the created key object, if
|
||||
any.
|
||||
|
||||
Return Value:
|
||||
|
||||
NTSTATUS
|
||||
|
||||
--*/
|
||||
{
|
||||
NTSTATUS status;
|
||||
PCELL_DATA pdata;
|
||||
HCELL_INDEX KeyCell;
|
||||
ULONG ParentType;
|
||||
ACCESS_MASK AdditionalAccess;
|
||||
BOOLEAN CreateAccess;
|
||||
PCM_KEY_BODY KeyBody;
|
||||
PSECURITY_DESCRIPTOR SecurityDescriptor;
|
||||
LARGE_INTEGER TimeStamp;
|
||||
BOOLEAN BackupRestore;
|
||||
KPROCESSOR_MODE mode;
|
||||
PCM_KEY_NODE ParentNode;
|
||||
#if DBG
|
||||
ULONG ChildConvKey;
|
||||
#endif
|
||||
HV_TRACK_CELL_REF CellRef = {0};
|
||||
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_PARSE,"CmpDoCreate:\n"));
|
||||
|
||||
BackupRestore = FALSE;
|
||||
if (ARGUMENT_PRESENT(Context)) {
|
||||
|
||||
if (Context->CreateOptions & REG_OPTION_BACKUP_RESTORE) {
|
||||
|
||||
//
|
||||
// allow backup operators to create new keys
|
||||
//
|
||||
BackupRestore = TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// Operation is a create, so set Disposition
|
||||
//
|
||||
Context->Disposition = REG_CREATED_NEW_KEY;
|
||||
}
|
||||
|
||||
#if DBG
|
||||
ChildConvKey = ParentKcb->ConvKey;
|
||||
|
||||
if (Name->Length) {
|
||||
ULONG Cnt;
|
||||
WCHAR *Cp;
|
||||
Cp = Name->Buffer;
|
||||
for (Cnt=0; Cnt<Name->Length; Cnt += sizeof(WCHAR)) {
|
||||
//
|
||||
// UNICODE_NULL is a valid char !!!
|
||||
//
|
||||
if (*Cp != OBJ_NAME_PATH_SEPARATOR) {
|
||||
//(*Cp != UNICODE_NULL)) {
|
||||
ChildConvKey = 37 * ChildConvKey + (ULONG)CmUpcaseUnicodeChar(*Cp);
|
||||
}
|
||||
++Cp;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT_HASH_ENTRY_LOCKED_EXCLUSIVE(ChildConvKey);
|
||||
ASSERT_KCB_LOCKED_EXCLUSIVE(ParentKcb);
|
||||
#endif
|
||||
CmpLockHiveFlusherShared((PCMHIVE)Hive);
|
||||
|
||||
if( CmIsKcbReadOnly(ParentKcb) ) {
|
||||
//
|
||||
// key is protected
|
||||
//
|
||||
status = STATUS_ACCESS_DENIED;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
//
|
||||
// make sure nothing changed in between:
|
||||
// 1. ParentKcb is still valid
|
||||
// 2. Child was not already added by somebody else
|
||||
//
|
||||
if( ParentKcb->Delete ) {
|
||||
//
|
||||
// key was deleted in between
|
||||
//
|
||||
status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
//
|
||||
// KeQuerySystemTime doesn't give us a fine resolution
|
||||
// so we have to search if the child has not been created already
|
||||
//
|
||||
ParentNode = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
|
||||
if( ParentNode == NULL ) {
|
||||
//
|
||||
// we couldn't map the bin containing this cell
|
||||
//
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if( !HvTrackCellRef(&CellRef,Hive,Cell) ) {
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if( CmpFindSubKeyByName(Hive,ParentNode,Name) != HCELL_NIL ) {
|
||||
//
|
||||
// key was changed in between; possibly this key was already created ==> reparse
|
||||
//
|
||||
status = STATUS_REPARSE;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if(!CmpOKToFollowLink(OriginatingHive,(PCMHIVE)Hive) ) {
|
||||
//
|
||||
// about to cross class of trust boundary
|
||||
//
|
||||
status = STATUS_ACCESS_DENIED;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
ASSERT( Cell == ParentKcb->KeyCell );
|
||||
|
||||
ASSERT( ParentKcb->CachedSecurity != NULL );
|
||||
SecurityDescriptor = &(ParentKcb->CachedSecurity->Descriptor);
|
||||
|
||||
ParentType = HvGetCellType(Cell);
|
||||
|
||||
if ( (ParentType == Volatile) &&
|
||||
((Context->CreateOptions & REG_OPTION_VOLATILE) == 0) )
|
||||
{
|
||||
//
|
||||
// Trying to create stable child under volatile parent, report error
|
||||
//
|
||||
status = STATUS_CHILD_MUST_BE_VOLATILE;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if (ParentKcb->Flags & KEY_SYM_LINK) {
|
||||
//
|
||||
// Disallow attempts to create anything under a symbolic link
|
||||
//
|
||||
status = STATUS_ACCESS_DENIED;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
AdditionalAccess = (Context->CreateOptions & REG_OPTION_CREATE_LINK) ? KEY_CREATE_LINK : 0;
|
||||
|
||||
if( BackupRestore == TRUE ) {
|
||||
//
|
||||
// this is a create to support a backup or restore
|
||||
// operation, do the special case work
|
||||
//
|
||||
AccessState->RemainingDesiredAccess = 0;
|
||||
AccessState->PreviouslyGrantedAccess = 0;
|
||||
|
||||
mode = KeGetPreviousMode();
|
||||
|
||||
if (SeSinglePrivilegeCheck(SeBackupPrivilege, mode)) {
|
||||
AccessState->PreviouslyGrantedAccess |=
|
||||
KEY_READ | ACCESS_SYSTEM_SECURITY;
|
||||
}
|
||||
|
||||
if (SeSinglePrivilegeCheck(SeRestorePrivilege, mode)) {
|
||||
AccessState->PreviouslyGrantedAccess |=
|
||||
KEY_WRITE | ACCESS_SYSTEM_SECURITY | WRITE_DAC | WRITE_OWNER;
|
||||
}
|
||||
|
||||
if (AccessState->PreviouslyGrantedAccess == 0) {
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_PARSE,"CmpDoCreate for backup restore: access denied\n"));
|
||||
status = STATUS_ACCESS_DENIED;
|
||||
//
|
||||
// this is not a backup-restore operator; deny the create
|
||||
//
|
||||
CreateAccess = FALSE;
|
||||
} else {
|
||||
//
|
||||
// allow backup operators to create new keys
|
||||
//
|
||||
status = STATUS_SUCCESS;
|
||||
CreateAccess = TRUE;
|
||||
}
|
||||
|
||||
} else {
|
||||
//
|
||||
// The FullName is not used in the routine CmpCheckCreateAccess,
|
||||
//
|
||||
CreateAccess = CmpCheckCreateAccess(NULL,
|
||||
SecurityDescriptor,
|
||||
AccessState,
|
||||
AccessMode,
|
||||
AdditionalAccess,
|
||||
&status);
|
||||
}
|
||||
|
||||
if (CreateAccess) {
|
||||
|
||||
//
|
||||
// Security check passed, so we can go ahead and create
|
||||
// the sub-key.
|
||||
//
|
||||
if ( !HvMarkCellDirty(Hive, Cell,FALSE) ) {
|
||||
status = STATUS_NO_LOG_SPACE;
|
||||
goto Exit;
|
||||
}
|
||||
//
|
||||
// Create and initialize the new sub-key
|
||||
//
|
||||
status = CmpDoCreateChild( Hive,
|
||||
Cell,
|
||||
SecurityDescriptor,
|
||||
AccessState,
|
||||
Name,
|
||||
AccessMode,
|
||||
Context,
|
||||
ParentKcb,
|
||||
0,
|
||||
&KeyCell,
|
||||
Object );
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
PCM_KEY_NODE KeyNode;
|
||||
|
||||
KeyBody = (PCM_KEY_BODY)(*Object);
|
||||
|
||||
//
|
||||
// Child successfully created, add to parent's list.
|
||||
//
|
||||
if (! CmpAddSubKey(Hive, Cell, KeyCell)) {
|
||||
//
|
||||
// Unable to add child, so free it
|
||||
//
|
||||
CmpFreeKeyByCell(Hive, KeyCell, FALSE);
|
||||
//
|
||||
// release the object created inside CmpDoCreateChild make sure kcb gets kicked out of cache
|
||||
//
|
||||
KeyBody->KeyControlBlock->Delete = TRUE;
|
||||
CmpRemoveKeyControlBlock(KeyBody->KeyControlBlock);
|
||||
ObDereferenceObjectDeferDelete(*Object);
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, Cell);
|
||||
if( KeyNode == NULL ) {
|
||||
//
|
||||
// we couldn't map the bin containing this cell
|
||||
// this shouldn't happen as we successfully marked the cell as dirty
|
||||
//
|
||||
ASSERT( FALSE );
|
||||
CmpFreeKeyByCell(Hive, KeyCell, TRUE);
|
||||
KeyBody->KeyControlBlock->Delete = TRUE;
|
||||
CmpRemoveKeyControlBlock(KeyBody->KeyControlBlock);
|
||||
ObDereferenceObjectDeferDelete(*Object);
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if( !HvTrackCellRef(&CellRef,Hive,Cell) ) {
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
CmpCleanUpSubKeyInfo (KeyBody->KeyControlBlock->ParentKcb);
|
||||
|
||||
//
|
||||
// Update max keyname and class name length fields
|
||||
//
|
||||
|
||||
//some sanity asserts first
|
||||
ASSERT( KeyBody->KeyControlBlock->ParentKcb->KeyCell == Cell );
|
||||
ASSERT( KeyBody->KeyControlBlock->ParentKcb->KeyHive == Hive );
|
||||
ASSERT( KeyBody->KeyControlBlock->ParentKcb == ParentKcb );
|
||||
ASSERT( KeyBody->KeyControlBlock->ParentKcb->KcbMaxNameLen == KeyNode->MaxNameLen );
|
||||
|
||||
//
|
||||
// update the LastWriteTime on both keynode and kcb;
|
||||
//
|
||||
KeQuerySystemTime(&TimeStamp);
|
||||
KeyNode->LastWriteTime = TimeStamp;
|
||||
KeyBody->KeyControlBlock->ParentKcb->KcbLastWriteTime = TimeStamp;
|
||||
|
||||
if (KeyNode->MaxNameLen < Name->Length) {
|
||||
KeyNode->MaxNameLen = Name->Length;
|
||||
// update the kcb cache too
|
||||
KeyBody->KeyControlBlock->ParentKcb->KcbMaxNameLen = Name->Length;
|
||||
}
|
||||
|
||||
if (KeyNode->MaxClassLen < Context->Class.Length) {
|
||||
KeyNode->MaxClassLen = Context->Class.Length;
|
||||
}
|
||||
|
||||
|
||||
if (Context->CreateOptions & REG_OPTION_CREATE_LINK) {
|
||||
pdata = HvGetCell(Hive, KeyCell);
|
||||
if( pdata == NULL ) {
|
||||
//
|
||||
// we couldn't map the bin containing this cell
|
||||
// this shouldn't happen as we just allocated the cell
|
||||
// (i.e. it must be PINNED into memory at this point)
|
||||
//
|
||||
ASSERT( FALSE );
|
||||
CmpFreeKeyByCell(Hive, KeyCell, TRUE);
|
||||
KeyBody->KeyControlBlock->Delete = TRUE;
|
||||
CmpRemoveKeyControlBlock(KeyBody->KeyControlBlock);
|
||||
ObDereferenceObjectDeferDelete(*Object);
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
pdata->u.KeyNode.Flags |= KEY_SYM_LINK;
|
||||
KeyBody->KeyControlBlock->Flags = pdata->u.KeyNode.Flags;
|
||||
HvReleaseCell(Hive,KeyCell);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
Exit:
|
||||
HvReleaseFreeCellRefArray(&CellRef);
|
||||
CmpUnlockHiveFlusher((PCMHIVE)Hive);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
NTSTATUS
|
||||
CmpDoCreateChild(
|
||||
IN PHHIVE Hive,
|
||||
IN HCELL_INDEX ParentCell,
|
||||
IN PSECURITY_DESCRIPTOR ParentDescriptor OPTIONAL,
|
||||
IN PACCESS_STATE AccessState,
|
||||
IN PUNICODE_STRING Name,
|
||||
IN KPROCESSOR_MODE AccessMode,
|
||||
IN PCM_PARSE_CONTEXT Context,
|
||||
IN PCM_KEY_CONTROL_BLOCK ParentKcb,
|
||||
IN USHORT Flags,
|
||||
OUT PHCELL_INDEX KeyCell,
|
||||
OUT PVOID *Object
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Creates a new sub-key. This is called by CmpDoCreate to create child
|
||||
sub-keys and CmpCreateLinkNode to create root sub-keys.
|
||||
|
||||
Arguments:
|
||||
|
||||
Hive - supplies a pointer to the hive control structure for the hive
|
||||
|
||||
ParentCell - supplies cell index of parent cell
|
||||
|
||||
ParentDescriptor - Supplies security descriptor of parent key, for use
|
||||
in inheriting ACLs.
|
||||
|
||||
AccessState - Running security access state information for operation.
|
||||
|
||||
Name - Supplies pointer to a UNICODE string which is the name of the
|
||||
child to be created.
|
||||
|
||||
AccessMode - Access mode of the original caller.
|
||||
|
||||
Context - Supplies pointer to CM_PARSE_CONTEXT structure passed through
|
||||
the object manager.
|
||||
|
||||
BaseName - Name of object create is relative to
|
||||
|
||||
KeyName - Relative name (to BaseName)
|
||||
|
||||
Flags - Supplies any flags to be set in the newly created node
|
||||
|
||||
KeyCell - Receives the cell index of the newly created sub-key, if any.
|
||||
|
||||
Object - Receives a pointer to the created key object, if any.
|
||||
|
||||
Return Value:
|
||||
|
||||
STATUS_SUCCESS - sub-key successfully created. New object is returned in
|
||||
Object, and the new cell's cell index is returned in KeyCell.
|
||||
|
||||
!STATUS_SUCCESS - appropriate error message.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
ULONG alloc=0;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
PCM_KEY_BODY KeyBody;
|
||||
HCELL_INDEX ClassCell=HCELL_NIL;
|
||||
PCM_KEY_NODE KeyNode;
|
||||
PCELL_DATA CellData;
|
||||
PCM_KEY_CONTROL_BLOCK kcb = NULL;
|
||||
ULONG StorageType;
|
||||
PSECURITY_DESCRIPTOR NewDescriptor = NULL;
|
||||
LARGE_INTEGER systemtime;
|
||||
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_PARSE,"CmpDoCreateChild:\n"));
|
||||
|
||||
//
|
||||
// Get allocation type
|
||||
//
|
||||
StorageType = Stable;
|
||||
|
||||
try {
|
||||
|
||||
if (Context->CreateOptions & REG_OPTION_VOLATILE) {
|
||||
StorageType = Volatile;
|
||||
}
|
||||
|
||||
//
|
||||
// Allocate child cell
|
||||
//
|
||||
*KeyCell = HvAllocateCell(
|
||||
Hive,
|
||||
CmpHKeyNodeSize(Hive, Name),
|
||||
StorageType,
|
||||
HCELL_NIL
|
||||
);
|
||||
if (*KeyCell == HCELL_NIL) {
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
leave;
|
||||
}
|
||||
alloc = 1;
|
||||
KeyNode = (PCM_KEY_NODE)HvGetCell(Hive, *KeyCell);
|
||||
if( KeyNode == NULL ) {
|
||||
//
|
||||
// we couldn't map the bin containing this cell
|
||||
// this shouldn't happen as we just allocated the cell
|
||||
// (i.e. it must be PINNED into memory at this point)
|
||||
//
|
||||
ASSERT( FALSE );
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
leave;
|
||||
}
|
||||
// release the cell right here as the view is pinned
|
||||
HvReleaseCell(Hive,*KeyCell);
|
||||
|
||||
//
|
||||
// Allocate cell for class name
|
||||
//
|
||||
if (Context->Class.Length > 0) {
|
||||
ClassCell = HvAllocateCell(Hive, Context->Class.Length, StorageType,*KeyCell);
|
||||
if (ClassCell == HCELL_NIL) {
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
leave;
|
||||
}
|
||||
}
|
||||
alloc = 2;
|
||||
//
|
||||
// Allocate the object manager object
|
||||
//
|
||||
Status = ObCreateObject(AccessMode,
|
||||
CmpKeyObjectType,
|
||||
NULL,
|
||||
AccessMode,
|
||||
NULL,
|
||||
sizeof(CM_KEY_BODY),
|
||||
0,
|
||||
0,
|
||||
Object);
|
||||
|
||||
if (NT_SUCCESS(Status)) {
|
||||
|
||||
KeyBody = (PCM_KEY_BODY)(*Object);
|
||||
|
||||
//
|
||||
// We have managed to allocate all of the objects we need to,
|
||||
// so initialize them
|
||||
//
|
||||
|
||||
//
|
||||
// Mark the object as uninitialized (in case we get an error too soon)
|
||||
//
|
||||
KeyBody->Type = KEY_BODY_TYPE;
|
||||
KeyBody->KeyControlBlock = NULL;
|
||||
|
||||
//
|
||||
// Fill in the class name
|
||||
//
|
||||
if (Context->Class.Length > 0) {
|
||||
|
||||
CellData = HvGetCell(Hive, ClassCell);
|
||||
if( CellData == NULL ) {
|
||||
//
|
||||
// we couldn't map the bin containing this cell
|
||||
// this shouldn't happen as we just allocated the cell
|
||||
// (i.e. it must be PINNED into memory at this point)
|
||||
//
|
||||
ASSERT( FALSE );
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
ObDereferenceObject(*Object);
|
||||
leave;
|
||||
}
|
||||
|
||||
// release the cell right here as the view is pinned (cell is dirty).
|
||||
HvReleaseCell(Hive,ClassCell);
|
||||
|
||||
try {
|
||||
|
||||
RtlCopyMemory(
|
||||
&(CellData->u.KeyString[0]),
|
||||
Context->Class.Buffer,
|
||||
Context->Class.Length
|
||||
);
|
||||
|
||||
} except(EXCEPTION_EXECUTE_HANDLER) {
|
||||
ObDereferenceObjectDeferDelete(*Object);
|
||||
Status = GetExceptionCode();
|
||||
leave;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Fill in the new key itself
|
||||
//
|
||||
KeyNode->Signature = CM_KEY_NODE_SIGNATURE;
|
||||
KeyNode->Flags = Flags;
|
||||
|
||||
KeQuerySystemTime(&systemtime);
|
||||
KeyNode->LastWriteTime = systemtime;
|
||||
|
||||
KeyNode->Spare = 0;
|
||||
KeyNode->Parent = ParentCell;
|
||||
KeyNode->SubKeyCounts[Stable] = 0;
|
||||
KeyNode->SubKeyCounts[Volatile] = 0;
|
||||
KeyNode->SubKeyLists[Stable] = HCELL_NIL;
|
||||
KeyNode->SubKeyLists[Volatile] = HCELL_NIL;
|
||||
KeyNode->ValueList.Count = 0;
|
||||
KeyNode->ValueList.List = HCELL_NIL;
|
||||
KeyNode->Security = HCELL_NIL;
|
||||
KeyNode->Class = ClassCell;
|
||||
KeyNode->ClassLength = Context->Class.Length;
|
||||
|
||||
KeyNode->MaxValueDataLen = 0;
|
||||
KeyNode->MaxNameLen = 0;
|
||||
KeyNode->MaxValueNameLen = 0;
|
||||
KeyNode->MaxClassLen = 0;
|
||||
|
||||
KeyNode->NameLength = CmpCopyName(Hive,
|
||||
KeyNode->Name,
|
||||
Name);
|
||||
if (KeyNode->NameLength < Name->Length) {
|
||||
KeyNode->Flags |= KEY_COMP_NAME;
|
||||
}
|
||||
|
||||
if (Context->CreateOptions & REG_OPTION_PREDEF_HANDLE) {
|
||||
KeyNode->ValueList.Count = (ULONG)((ULONG_PTR)Context->PredefinedHandle);
|
||||
KeyNode->Flags |= KEY_PREDEF_HANDLE;
|
||||
}
|
||||
|
||||
//
|
||||
// Create kcb here so all data are filled in.
|
||||
//
|
||||
// Allocate a key control block
|
||||
//
|
||||
kcb = CmpCreateKeyControlBlock(Hive, *KeyCell, KeyNode, ParentKcb, CMP_CREATE_KCB_KCB_LOCKED, Name);
|
||||
if (kcb == NULL) {
|
||||
ObDereferenceObjectDeferDelete(*Object);
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
leave;
|
||||
}
|
||||
ASSERT(kcb->RefCount == 1);
|
||||
alloc = 3;
|
||||
|
||||
#if DBG
|
||||
if( kcb->ExtFlags & CM_KCB_KEY_NON_EXIST ) {
|
||||
//
|
||||
// we shouldn't fall into this
|
||||
//
|
||||
ObDereferenceObjectDeferDelete(*Object);
|
||||
DbgBreakPoint();
|
||||
Status = STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
leave;
|
||||
}
|
||||
#endif //DBG
|
||||
//
|
||||
// Fill in CM specific fields in the object
|
||||
//
|
||||
KeyBody->Type = KEY_BODY_TYPE;
|
||||
KeyBody->KeyControlBlock = kcb;
|
||||
KeyBody->NotifyBlock = NULL;
|
||||
KeyBody->ProcessID = PsGetCurrentProcessId();
|
||||
EnlistKeyBodyWithKCB(KeyBody,CMP_ENLIST_KCB_LOCKED_EXCLUSIVE);
|
||||
//
|
||||
// Assign a security descriptor to the object. Note that since
|
||||
// registry keys are container objects, and ObAssignSecurity
|
||||
// assumes that the only container object in the world is
|
||||
// the ObpDirectoryObjectType, we have to call SeAssignSecurity
|
||||
// directly in order to get the right inheritance.
|
||||
//
|
||||
|
||||
Status = SeAssignSecurity(ParentDescriptor,
|
||||
AccessState->SecurityDescriptor,
|
||||
&NewDescriptor,
|
||||
TRUE, // container object
|
||||
&AccessState->SubjectSecurityContext,
|
||||
&CmpKeyObjectType->TypeInfo.GenericMapping,
|
||||
CmpKeyObjectType->TypeInfo.PoolType);
|
||||
if (NT_SUCCESS(Status)) {
|
||||
CmLockHiveSecurityExclusive((PCMHIVE)kcb->KeyHive);
|
||||
//
|
||||
// force assign to the new kcb, by passing NULL as the trans
|
||||
//
|
||||
Status = CmpAssignSecurityDescriptorWrapper(*Object,NewDescriptor);
|
||||
CmUnlockHiveSecurity((PCMHIVE)kcb->KeyHive);
|
||||
}
|
||||
|
||||
//
|
||||
// Since the security descriptor now lives in the hive,
|
||||
// free the in-memory copy
|
||||
//
|
||||
SeDeassignSecurity( &NewDescriptor );
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
|
||||
//
|
||||
// Note that the dereference will clean up the kcb, so
|
||||
// make sure and decrement the allocation count here.
|
||||
//
|
||||
// Also mark the kcb as deleted so it does not get
|
||||
// inappropriately cached.
|
||||
//
|
||||
kcb->Delete = TRUE;
|
||||
CmpRemoveKeyControlBlock(kcb);
|
||||
ObDereferenceObjectDeferDelete(*Object);
|
||||
alloc = 2;
|
||||
|
||||
} else {
|
||||
CmpReportNotify(
|
||||
kcb,
|
||||
kcb->KeyHive,
|
||||
kcb->KeyCell,
|
||||
REG_NOTIFY_CHANGE_NAME
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
} finally {
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
|
||||
//
|
||||
// Clean up allocations
|
||||
//
|
||||
switch (alloc) {
|
||||
case 3:
|
||||
//
|
||||
// Mark KCB as deleted so it does not get inadvertently added to
|
||||
// the delayed close list. That would have fairly disastrous effects
|
||||
// as the KCB points to storage we are about to free.
|
||||
//
|
||||
kcb->Delete = TRUE;
|
||||
CmpRemoveKeyControlBlock(kcb);
|
||||
CmpDereferenceKeyControlBlockWithLock(kcb,FALSE);
|
||||
// DELIBERATE FALL
|
||||
|
||||
case 2:
|
||||
if (Context->Class.Length > 0) {
|
||||
HvFreeCell(Hive, ClassCell);
|
||||
}
|
||||
// DELIBERATE FALL
|
||||
|
||||
case 1:
|
||||
HvFreeCell(Hive, *KeyCell);
|
||||
// DELIBERATE FALL
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(Status);
|
||||
}
|
||||
191
base/ntos/config/cmpbug.h
Normal file
191
base/ntos/config/cmpbug.h
Normal file
@ -0,0 +1,191 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
cmpbug.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Description of the registry bugchecks; only defines and comments.
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef __CMPBUG_H__
|
||||
#define __CMPBUG_H__
|
||||
|
||||
#define CM_BUGCHECK( Code, Parm1, Parm2, Parm3, Parm4 ) \
|
||||
KeBugCheckEx( (ULONG)Code, (ULONG_PTR)Parm1, (ULONG_PTR)Parm2, (ULONG_PTR)Parm3, (ULONG_PTR)Parm4 )
|
||||
|
||||
|
||||
/* -
|
||||
CRITICAL_SERVICE_FAILED (0x5A)
|
||||
*/
|
||||
/* -
|
||||
SET_ENV_VAR_FAILED (0x5B)
|
||||
*/
|
||||
|
||||
#define BAD_LAST_KNOWN_GOOD 1 //CmBootLastKnownGood
|
||||
|
||||
|
||||
/* -
|
||||
CONFIG_LIST_FAILED (0x73)
|
||||
Indicates that one of the core system hives cannot be linked in the
|
||||
registry tree. The hive is valid, it was loaded OK. Examine the 2nd
|
||||
bugcheck argument to see why the hive could not be linked in the
|
||||
registry tree.
|
||||
|
||||
PARAMETERS
|
||||
1 - 1
|
||||
2 - Indicates the NT status code that tripped us into thinking
|
||||
that we failed to load the hive.
|
||||
3 - Index of hive in hivelist
|
||||
4 - Pointer to UNICODE_STRING containing filename of hive
|
||||
|
||||
DESCRIPTION
|
||||
This can be either SAM, SECURITY, SOFTWARE or DEFAULT. One common reason
|
||||
for this to happen is if you are out of disk space on the system drive
|
||||
(in which case param 4 is 0xC000017D - STATUS_NO_LOG_SPACE) or an attempt
|
||||
to allocate pool has failed (in which case param 4 is 0xC000009A -
|
||||
STATUS_INSUFFICIENT_RESOURCES). Other status codes must be individually
|
||||
investigated.
|
||||
*/
|
||||
|
||||
#define BAD_CORE_HIVE 1 // CmpInitializeHiveList
|
||||
|
||||
/* -
|
||||
BAD_SYSTEM_CONFIG_INFO (0x74)
|
||||
Can indicate that the SYSTEM hive loaded by the osloader/NTLDR
|
||||
was corrupt. This is unlikely, since the osloader will check
|
||||
a hive to make sure it isn't corrupt after loading it.
|
||||
|
||||
It can also indicate that some critical registry keys and values
|
||||
are not present. (i.e. somebody used regedt32 to delete something
|
||||
that they shouldn't have) Booting from LastKnownGood may fix
|
||||
the problem, but if someone is persistent enough in mucking with
|
||||
the registry they will need to reinstall or use the Emergency
|
||||
Repair Disk.
|
||||
|
||||
PARAMETERS
|
||||
1 - identifies the function
|
||||
2 - identifies the line inside the function
|
||||
3 - other info
|
||||
4 - usually the NT status code.
|
||||
*/
|
||||
|
||||
#define BAD_SYSTEM_CONTROL_VALUES 1 // CmGetSystemControlValues
|
||||
|
||||
#define BAD_HIVE_LIST 2 // CmpInitializeHiveList
|
||||
|
||||
#define BAD_SYSTEM_HIVE 3 // CmpInitializeSystemHive
|
||||
|
||||
|
||||
|
||||
/* -
|
||||
CONFIG_INITIALIZATION_FAILED (0x67)
|
||||
|
||||
PARAMETERS
|
||||
1 - indicates location in ntos\config\cmsysini that failed
|
||||
2 - location selector
|
||||
3 - NT status code
|
||||
|
||||
DESCRIPTION
|
||||
This means the registry couldn't allocate the pool needed to contain the
|
||||
registry files. This should never happen, since it is early enough in
|
||||
system initialization that there is always plenty of paged pool available.
|
||||
*/
|
||||
|
||||
#define INIT_SYSTEM1 1 // CmInitSystem1
|
||||
|
||||
#define INIT_SYSTEM_DRIVER_LIST 2 // CmGetSystemDriverList
|
||||
|
||||
#define INIT_CACHE_TABLE 3 // CmpInitializeCache
|
||||
|
||||
#define INIT_DELAYED_CLOSE_TABLE 4 // CmpInitializeDelayedCloseTable
|
||||
|
||||
|
||||
/* -
|
||||
CANNOT_WRITE_CONFIGURATION (0x75)
|
||||
|
||||
This will result if the SYSTEM hive file cannot be converted to a
|
||||
mapped file. This usually happens if the system is out of pool and
|
||||
we cannot reopen the hive.
|
||||
|
||||
PARAMETERS
|
||||
1 - 1
|
||||
2 - Indicates the NT status code that tripped us into thinking
|
||||
that we failed to convert the hive.
|
||||
|
||||
DESCRIPTION
|
||||
Normally you shouldn't see this as the conversion happens at early
|
||||
during system initialization, so enough pool should be available.
|
||||
*/
|
||||
|
||||
#define CANNOT_CONVERT_SYSTEM_HIVE 1
|
||||
|
||||
|
||||
/* -
|
||||
REGISTRY_ERROR (0x51)
|
||||
PARAMETERS
|
||||
1 - value 1 (indicates where we bugchecked)
|
||||
2 - value 2 (indicates where we bugchecked)
|
||||
3 - depends on where it bugchecked, may be pointer to hive
|
||||
4 - depends on where it bugchecked, may be return code of
|
||||
HvCheckHive if the hive is corrupt.
|
||||
|
||||
DESCRIPTION
|
||||
Something has gone horribly wrong with the registry. If a kernel debugger
|
||||
is available, get a stack trace.It can also indicate that the registry got
|
||||
an I/O error while trying to read one of its files, so it can be caused by
|
||||
hardware problems or filesystem corruption.
|
||||
|
||||
It may occur due to a failure in a refresh operation, which is used only
|
||||
in by the security system, and then only when resource limits are encountered.
|
||||
*/
|
||||
|
||||
#define BAD_CELL_MAP 1 // VALIDATE_CELL_MAP
|
||||
|
||||
#define BAD_FREE_BINS_LIST 2 // HvpDelistBinFreeCells
|
||||
|
||||
#define FATAL_MAPPING_ERROR 3 // HvpFindNextDirtyBlock
|
||||
// HvpDoWriteHive
|
||||
|
||||
#define BAD_SECURITY_CACHE 4 // CmpAssignSecurityToKcb
|
||||
// CmpSetSecurityDescriptorInfo
|
||||
|
||||
#define BAD_SECURITY_METHOD 5 // CmpSecurityMethod
|
||||
|
||||
#define CHECK_LOCK_EXCEPTION 6 // CmpCheckLockExceptionFilter
|
||||
|
||||
#define REGISTRY_LOCK_CHECKPOINT 7 // END_LOCK_CHECKPOINT
|
||||
|
||||
#define BIG_CELL_ERROR 8 // CmpValueToData
|
||||
|
||||
#define CMVIEW_ERROR 9 // CmpAllocateCmView
|
||||
// CmpFreeCmView
|
||||
// CmpPinCmView
|
||||
|
||||
#define REFRESH_HIVE 0xA // HvRefreshHive
|
||||
|
||||
|
||||
#define ALLOCATE_SECURITY_DESCRIPTOR 0xB // CmpHiveRootSecurityDescriptor
|
||||
|
||||
#define BAD_NOTIFY_CONTEXT 0xC // NtNotifyChangeMultipleKeys
|
||||
|
||||
|
||||
#define QUOTA_ERROR 0xD // CmpReleaseGlobalQuota
|
||||
|
||||
#define INVALID_WRITE_OPERATION 0xE // NtCreateKey
|
||||
|
||||
#define HANDLES_STILL_OPEN_AT_SHUTDOWN 0xF // CmFreeAllMemory
|
||||
|
||||
#define COMPRESS_HIVE 0x10 // CmCompressKey
|
||||
|
||||
#define ALLOC_ERROR 0x11 // CmpFreeKeyControlBlock
|
||||
|
||||
#endif // _CMPBUG_
|
||||
161
base/ntos/config/cmquery.c
Normal file
161
base/ntos/config/cmquery.c
Normal file
@ -0,0 +1,161 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
|
||||
If you do not agree to the terms, do not use the code.
|
||||
|
||||
|
||||
Module Name:
|
||||
|
||||
cmquery.c
|
||||
|
||||
Abstract:
|
||||
|
||||
This module contains the object name query method for the registry.
|
||||
|
||||
--*/
|
||||
|
||||
#include "cmp.h"
|
||||
|
||||
#ifdef ALLOC_PRAGMA
|
||||
#pragma alloc_text(PAGE,CmpQueryKeyName)
|
||||
#endif
|
||||
|
||||
NTSTATUS
|
||||
CmpQueryKeyName(
|
||||
IN PVOID Object,
|
||||
IN BOOLEAN HasObjectName,
|
||||
OUT POBJECT_NAME_INFORMATION ObjectNameInfo,
|
||||
IN ULONG Length,
|
||||
OUT PULONG ReturnLength,
|
||||
IN KPROCESSOR_MODE Mode
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine interfaces to the NT Object Manager. It is invoked when
|
||||
the object system wishes to discover the name of an object that
|
||||
belongs to the registry.
|
||||
|
||||
Arguments:
|
||||
|
||||
Object - pointer to a Key, thus -> KEY_BODY.
|
||||
|
||||
HasObjectName - indicates whether the object manager knows about a name
|
||||
for this object
|
||||
|
||||
ObjectNameInfo - place where we report the name
|
||||
|
||||
Length - maximum length they can deal with
|
||||
|
||||
ReturnLength - supplies variable to receive actual length
|
||||
|
||||
Mode - Processor mode of the caller
|
||||
|
||||
Return Value:
|
||||
|
||||
STATUS_SUCCESS
|
||||
|
||||
STATUS_INFO_LENGTH_MISMATCH
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
PUNICODE_STRING Name = NULL;
|
||||
PWCHAR t;
|
||||
PWCHAR s;
|
||||
ULONG l;
|
||||
NTSTATUS status;
|
||||
PCM_KEY_CONTROL_BLOCK kcb;
|
||||
BOOLEAN UnlockKcb = TRUE;
|
||||
|
||||
UNREFERENCED_PARAMETER(HasObjectName);
|
||||
UNREFERENCED_PARAMETER(Mode);
|
||||
|
||||
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_PARSE,"CmpQueryKeyName:\n"));
|
||||
|
||||
BEGIN_LOCK_CHECKPOINT;
|
||||
CmpLockRegistry();
|
||||
//
|
||||
// sanitize the kcb, for cases where we get a callback for se audit
|
||||
//
|
||||
kcb = (PCM_KEY_CONTROL_BLOCK)(((PCM_KEY_BODY)Object)->KeyControlBlock);
|
||||
if( (ULONG_PTR)kcb & 1 ) {
|
||||
kcb = (PCM_KEY_CONTROL_BLOCK)((ULONG_PTR)kcb ^ 1);
|
||||
ASSERT_KCB_LOCKED(kcb);
|
||||
UnlockKcb = FALSE;
|
||||
} else {
|
||||
CmpLockKCBShared(kcb);
|
||||
}
|
||||
|
||||
if ( kcb->Delete) {
|
||||
if( UnlockKcb ) {
|
||||
CmpUnlockKCB(kcb);
|
||||
}
|
||||
CmpUnlockRegistry();
|
||||
return STATUS_KEY_DELETED;
|
||||
}
|
||||
Name = CmpConstructName(kcb);
|
||||
|
||||
if( UnlockKcb ) {
|
||||
CmpUnlockKCB(kcb);
|
||||
}
|
||||
|
||||
//
|
||||
// don't need the lock anymore
|
||||
//
|
||||
CmpUnlockRegistry();
|
||||
END_LOCK_CHECKPOINT;
|
||||
|
||||
if (Name == NULL) {
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
return status;
|
||||
}
|
||||
|
||||
if (Length <= sizeof(OBJECT_NAME_INFORMATION)) {
|
||||
*ReturnLength = Name->Length + sizeof(WCHAR) + sizeof(OBJECT_NAME_INFORMATION);
|
||||
ExFreePoolWithTag(Name, CM_NAME_TAG | PROTECTED_POOL);
|
||||
return STATUS_INFO_LENGTH_MISMATCH; // they can't even handle null
|
||||
}
|
||||
|
||||
t = (PWCHAR)(ObjectNameInfo + 1);
|
||||
s = Name->Buffer;
|
||||
l = Name->Length;
|
||||
l += sizeof(WCHAR); // account for null
|
||||
|
||||
*ReturnLength = l + sizeof(OBJECT_NAME_INFORMATION);
|
||||
if (l > Length - sizeof(OBJECT_NAME_INFORMATION)) {
|
||||
l = Length - sizeof(OBJECT_NAME_INFORMATION);
|
||||
status = STATUS_INFO_LENGTH_MISMATCH;
|
||||
if( l < sizeof(WCHAR) ) {
|
||||
ExFreePoolWithTag(Name, CM_NAME_TAG | PROTECTED_POOL);
|
||||
return status; // they can't even handle null
|
||||
}
|
||||
} else {
|
||||
status = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
l -= sizeof(WCHAR);
|
||||
|
||||
//
|
||||
// The ObjectNameInfo buffer is a usermode buffer, so make sure we have an
|
||||
// exception handler in case a malicious app changes the protection out from
|
||||
// under us.
|
||||
//
|
||||
// Note the object manager is responsible for probing the buffer and ensuring
|
||||
// that a top-level exception handler returns the correct error code. We just
|
||||
// need to make sure we drop our lock.
|
||||
//
|
||||
try {
|
||||
RtlCopyMemory(t, s, l);
|
||||
t[l/sizeof(WCHAR)] = UNICODE_NULL;
|
||||
ObjectNameInfo->Name.Length = (USHORT)l;
|
||||
ObjectNameInfo->Name.MaximumLength = ObjectNameInfo->Name.Length;
|
||||
ObjectNameInfo->Name.Buffer = t;
|
||||
} finally {
|
||||
ExFreePoolWithTag(Name, CM_NAME_TAG | PROTECTED_POOL);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
2640
base/ntos/config/cmsavres.c
Normal file
2640
base/ntos/config/cmsavres.c
Normal file
File diff suppressed because it is too large
Load Diff
2328
base/ntos/config/cmse.c
Normal file
2328
base/ntos/config/cmse.c
Normal file
File diff suppressed because it is too large
Load Diff
1126
base/ntos/config/cmsecache.c
Normal file
1126
base/ntos/config/cmsecache.c
Normal file
File diff suppressed because it is too large
Load Diff
2562
base/ntos/config/cmsubs.c
Normal file
2562
base/ntos/config/cmsubs.c
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user