苹果降级the application is load errorinvalidd load library failed 怎么处理

 上传我的文档
 下载
 收藏
该文档贡献者很忙,什么也没留下。
 下载此文档
正在努力加载中...
When the computer is turned on, the blue screen code is fully parsed
下载积分:2000
内容提示:When the computer is turned on, the blue screen code is fully parsed
文档格式:DOC|
浏览次数:0|
上传日期: 22:26:47|
文档星级:
全文阅读已结束,如果下载本文需要使用
 2000 积分
下载此文档
该用户还上传了这些文档
When the computer is turned on, the blue screen co
关注微信公众号The LoadLibrary Explorer
The LoadLibrary Explorer
&There is a lot of confusion about the way LoadLibrary and
LoadLibraryEx work, especially given the various security changes made in
Windows 2000, Windows XP, and Server 2003 Service Packs.& I needed to get
the correct information about how this worked, and consequently had to create a
program that actually did these calls.& The results are a bit surprising.&
Not only is there a lot of incorrect folklore and misinterpretation out there
about what is going on, but the documentation itself appears to be incorrect.&
Appears to be lying it its teeth, to make an understatement.
There are many factors that determine where a DLL is found during a load.&
They include
loading a DLL
The effects of the SafeDllSearchMode Registry setting (which
appears to have no effect)
The effects of
SP1 and higher, Server 2003 and higher)
The effects of the .local mechanism for
although documented, apparently does not work)
The effects of the
Registry setting
(which requires that ShellExecute(Ex) is used to launch the program)
This program explores how LoadLibrary and LoadLlibraryEx work
by allowing you to install a DLL in a specific place, or places, and then see
from which place it was loaded.
Here's the documentation from the LoadLibrary documentation in the
is 1 (the default), the search order is as
The directory from which the application loaded.
The system directory. Use the
GetSystemDirectory function to get the path of this
directory.
The 16-bit system directory. There is no function that obtains the path of
this directory, but it is searched.
Windows Me/98/95:&&This directory does not exist.
The Windows directory. Use the
GetWindowsDirectory function to get the path of this
directory.
The current directory.
The directories that are listed in the PATH environment variable.
is 0, the search order is as follows:
The directory from which the application loaded.
The current directory.
The system directory. Use the GetSystemDirectory function to get
the path of this directory.
The 16-bit system directory. There is no function that obtains the path of
this directory, but it is searched.
Windows Me/98/95:&&This directory does not exist.
The Windows directory. Use the GetWindowsDirectory function to get
the path of this directory.
The directories that are listed in the PATH environment variable.
Windows XP:&&The default value of HKLM\System\CurrentControlSet\Control\Session
Manager\ is 0 (the current directory is searched before
the system and Windows directories).
LoadLibraryEx is equally explicit: Not only is the above stated, but in
addition, there is the description
If a path is specified and dwFlags is set to
LOAD_WITH_ALTERED_SEARCH_PATH, the LoadLibraryEx function uses an
alternate file search strategy. The search order used depends on the setting of
the HKLM\System\CurrentControlSet\Control\Session Manager\
If SafeDllSearchMode is 1 (the default), the alternate search order is
as follows:
The directory specified by the lpFileName path. In other
words, the directory that the specified executable module is in.
The system directory. Use the
GetSystemDirectory function to get the path of this
directory.
The 16-bit system directory. There is no function that obtains the path of
this directory, but it is searched.
Windows Me/98/95:&&This directory does not exist.
The Windows directory. Use the
GetWindowsDirectory function to get the path of this
directory.
The current directory.
The directories that are listed in the PATH environment variable.
is 0, the alternate search order is as follows:
The directory specified by the lpFileName path. In other
words, the directory that the specified executable module is in.
The current directory.
The system directory. Use the GetSystemDirectory function to get
the path of this directory.
The 16-bit system directory. There is no function that obtains the path of
this directory, but it is searched.
Windows Me/98/95:&&This directory does not exist.
The Windows directory. Use the GetWindowsDirectory function to get
the path of this directory.
The directories that are listed in the PATH environment variable.
Using the LoadLibrary Explorer, you can demonstrate that this is not
the behavior you actually see in real programs on real systems.& For
example, if LOAD_WITH_ALTERED_SEARCH_PATH is used and an explicit path is
given, and the file does not exist in that explicit path, the operation fails
immediately, even if the DLL does exist in other directories specified
for the search order!
Using the LoadLibrary Explorer
When the LoadLibrary Explorer is loaded, the startup screen resembles the one
shown below
This represents the startup state.& Details may differ slightly in terms
of initialization.
Selecting the desired directories
There are a set of check boxes that allow the selection of the locations into
which the DLL will be placed (more later on which DLL is placed in these
directories, for now assume a canonical DLL that comes with the project).&
When the Load button is pressed, the LoadLibrary (or
LoadLibraryEx) call will be executed.& If the module is successfully
loaded, the library path used will be displayed, and highlighted in the controls
as shown below.
In the above example, the System32, System and Executable
directories are all selected.& Because of the search rules in force at the
time LoadLibrary was executed, the DLL is found in the executable
directory.
Selecting the load method
The two viable options supported right now are LoadLibrary and
LoadLibraryEx.& In the above example, LoadLibrary has been
selected.& The other supported option is LoadLibraryEx.
Loading the DLL
Clicking the Load button will take the following actions:
All directories that are checked will have the DLL copied to them
All directories that are unchecked will have the DLL deleted from them
The selected operation will be executed
The result is displayed in the Library Path Loaded box
The DLL that is loaded is also highlighted&& (This reflects the
information in the log window and in the Library Path Loaded box and
makes it easier to see where the DLL came from).
The boxes display the state of the library-copy operation.& Values which
may be displayed include
Installed - The DLL was copied to the directory
Already gone - The DLL did not exist in the directory
Already there - The DLL was already in the directory
No source - the desired DLL cannot be copied because the source
cannot be opened.& Check the log window for the details/
Error - There was an error copying the file to the target.&
Check the log window for the details.
Copy error - There was an error copying the file.& Check the
log window for the details.
Known DLL - The DLL is a &known DLL& and was not copied.
The complete details of the DLL installation are displayed in the log window.
Selecting the DLL to be loaded
If the (Internal DLL)
option is selected, the program uses a DLL that is built as part of the project,
which is stored in the executable directory as
theDLL.xxx in the executable directory.
To illustrate the effect of the &Known DLLs&, the Known&DLL option can
be selected, which will then loadr one of the Known DLLs.& Note that while
a Known DLL can be installed in any of the selected directories,& (except
the System32 directory, which is disabled), any attempt to load a known DLL
should come from the System32 directory.
The Known DLLs combo box gives the list of &known DLLs& from
the key HKLM\System\CurrentControlSet\Control\Session&Manager\KnownDLLs.&
Those DLLs with a checkmark beside the name have already been loaded into the
process image, and would not be good candidates for selection to demonstrate the
effect of a dynamic load.
The path, here shown as %SystemRoot%\System32, is obtained from the
key HKLM\System\CurrentControlSet\Control\Session&Manager\KnownDLLs\dllDirectory.&
It will be properly in the machine on which this was
running it became c:\Windows\System32.
The effect of trying to load
the selected urlmon.dll is shown at the left.& Note that the
System32 directory is disabled, and its checked status will be ignored.&
But in spite of this, the DLL is loaded from the Known DLLs directory,
and the other directories are ignored.& This demonstrates that certain
forms of spoofing of these DLLs would not be possible.
Selecting the Load method
There are two options supported.& The first is the straight
LoadLibrary call.& The second is using LoadLibraryEx.& When
using LoadLibraryEx, the option, the flag
LOAD_WITH_ALTERED_SEARCH_PATH can be selected (the other flags for
LoadLibraryEx options are not supported).& And here is where one of the
bugs in the documentation is revealed.&
if the LOAD_WITH_ALTERED_SEARCH_PATH option is specified, and an explicit
path is given, and the DLL is not found in that directory, then the behavior
reverts to the default search as if a path had not been specified. But it
doesn't actually work that way!
To provide an explicit path,
the Use&Explicit&Path&Above option is used, and the options are limited
to one of the directories in the list (this is sufficient for demonstrating the
failure mode).& With the selection shown, the generated call is
LoadLibraryEx(_T(&i:\mvp_tips\LoadLibraryExplorer\debug\Working\TheDLL.dll&),
NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
But when the Load button is selected, the explicit path fails (note
there is no check mark that causes the DLL to be placed in the selected target
directory).& The documented behavior, of using the search logic, fails
completely.
The directories
When the program starts up, it creates a set of directories under the
executable directory.& These are
Working - The program does a SetCurrentDirectory to this
directory.
AppPath - This will be used if the AppPath feature is
Alternate - This is used as the target for a SetDllDirectory
.local- Only created when Redirect to Directory is selected
SetDllDirectory is available only for Windows XP Service Pack 1 and
beyond and Server 2003 and beyond.& It is not available on Windows 2000 or
below.& If the LoadLibrary Explorer is run on an earlier version of
Windows, the Alternate options will be disabled.& When Alternate
is selected, the DLL search order is
The executable directory
The SetDllDirectory directory
The System32 directory
The System directory
The Windows directory
The PATH= directories
Whenever Alternate is chosen, the DLL will be installed in the
Alternate directory and SetDllDirectory will be called referencing
that directory.
For any application, there is an entry in the HKEY_LOCAL_MACHINE key
which indicates two pieces of information.
The key is HKLM\Software\Microsofot\Windows\CurrentVersion\App Paths\name_of_executable_file
and it has two values: the (default) value and the Path
value, as shown below in a screen snapshot of the Registry Editor.
Note that under the key HKLM\SOFTEARE\Microsoft\Windows\CurrentVersion\App&Paths\LoadLibraryExplorer.exe,
the value (Default) is given as i:\mvp_tips\LoadLibraryExplorer\debug\LoadLibraryExplorer.exe.&
This value is used if there is a shell shortcut that names only
LoadLibraryExplorer.exe will be able to find the actual executable image.&
When this app is launched with ShellExecute(Ex), the Path value is
checked.& If it exists, its value is added to the PATH= &list.&
If the AppPath option is checked, and these keys do not already exist,
they will be created.& However, there are possible inconsistencies.
If the program was launched via ShellExecute, with the Path
key defined, but the App&Path is not selected, the DLL would be loaded
If the program was not launched via ShellExecute, or the Path
key was not defined, and the App&Path option is selected, the
AppPath directory will not be used.
In either case, it is necessary to re-launch the executable.& This is
accomplished by using the Re-Launch LoadLibrary Explorer button.&
This button is enabled whenever there is an inconsistency between the actual
state and the desired state.
Note that after the launch, examining the PATH list shows the
AppPath directory has been added.& The list has been scrolled to the
end. to show this.
Note from the above documentation that the SafeDllSearchMode key, HKLM\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode,
the effect is to deemphasize the role of the working directory, pushing it lower
this reduces the chances of a spoofing attack that replaces
a system DLL.
To test this, it was necessary to launch a secondary program which had an
implicit link to the target DLL. This program then notifies the launching
process what DLL was loaded.& This technique pointed out another issue.&
Although I illustrate the call as being ShellExecute, I actually use
ShellExecuteEx, and specify the
SEE_MASK_FLAG_NO_UI option, which states &Do not display an error message
box if an error occurs&.& However, while one might be led to suspect that
this is going to set the SetErrorMode state in the child process, it
apparently has no effect.& If there is a DLL load failure, the image below
shows what happens.
Independent of the setting of the SafeDllSearchMode, launching a
program where there is a copy of the DLL in both the System32 and the
Working directory, the version from the Working directory is always
The above behavior is expected.& The copy in the working directory is
found first, because the dcoumented search path is
The directory from which the application loaded.
The current directory.
The system directory. Use the GetSystemDirectory function to get
the path of this directory.
The 16-bit system directory. There is no function that obtains the path of
this directory, but it is searched.
The Windows directory. Use the GetWindowsDirectory function to get
the path of this directory.
The directories that are listed in the PATH environment variable.
But when SafeDllSearchMode is set to 1, the result is
The correct target should have been the System32 directory, according
to the documentation:
The directory from which the application loaded.
The system directory. Use the
GetSystemDirectory function to get the path of this
directory.
The 16-bit system directory. There is no function that obtains the path of
this directory, but it is searched.
The Windows directory. Use the
GetWindowsDirectory function to get the path of this
directory.
The current directory.
The directories that are listed in the PATH environment variable.
but that is not the behavior exhibited here.&
Read the article in the MSDN titled &Dynamic-Link Library Redirection&, which
is found either by direct searching or under the topic
Win32 and COM Development
&& System, Services
&&&&& DLLs, Processes and Threads
&&&&&&&& SDK Documentation
&&&&&&&&&&& DLLs,
Processes and Threads
&&&&&&&&&&&&&&
Dynamic-Link Libraries
&&&&&&&&&&&&&&&&&
About Dynamic-Link Libraries
&&&&&&&&&&&&&&&&&&&&
Dynamic-Link Library Redirection
The goal here is to demonstrate how to install what are called &side-by-side
components& so your app will run with the appropriate version of a given DLL.
There are three options here
No redirection
Redirection via a .local file (Executable directory)
Redirection via a .local directory
The documentation states that when redirection takes place via a
.local file, the DLL that is desired is
placed in the executable directory.& No matter what path is actually specified in LoadLibrary(Ex)
call, the system first checks to see if there is an
application_name.local file in the executable directory.& If
there is, then the LoadLibrary call will ignore the specified path and
load the DLL from the executable directory
otherwise, the
standard search mechanism will be used.
When rediretion takes place via a .local directory, a directory named
application_name.local is created in the
executable directory, and the DLL is installed in this directory.&
LoadLibrary(Ex) calls will ignore any explicit path and load the target DLL
from that directory if it is found there, otherwise the standard search
mechanism will be used.
Numerous experiments suggest that this method of redirection does not
actually work in Windows XP SP2 or Server 2003!& For example, see the
screen snapshot below:
and just to verify that the directory actually exists, and the file exists
within it:
As can be seen from either the log listing in the LoadLibrary Explorer, or
from the command shell snapshot, the directory i:\mvp_tips\LoadLibraryExplorer\debug\LoadLibraryExplorer.exe.local
definitely exists, and it definitely contains the specified target, &TheDLL.dll&,
but the load fails.& All variants of attempts to load from this directory
appear to fail.& Yet I saw it work once, and have not been able to
determine the confluence of circumstances that created that one-and-only event.&
Certainly everything I see in the example just illustrated suggest that there
are problems here.& Perhaps someone with more time than I have left right
now can figure out what is happening (if so, send me email, and I'll add your
information and give you a credit line!)
The module list
The EnumProcessModules button
invokes the EnumProcessModules API and creates a list of all the modules.&
If the Alphabetical option is selected, they will be displayed in
alphabetical order.
The module list is displayed
in the log window.
Bug summary
Using the LoadLibrary Explorer, I have determined the following bugs appear
in the Microsoft documentation:
Dynamic-Link Library Redirection, the use of the .local file or directory,
does not work in Windows XP SP2 or Windows Server 2003.
SafeDllSearchMode does not work even for load-time dynamic linking
LOAD_WITH_ALTERED_SEARCH_PATH if the DLL is not found
in the directory with the given path, it does not change the behavior of either
implicit or explicit dynamic linking.
Useful Programming Techniques
Like most projects, this project illustrates a number of useful programming
techniques.
Extracting a DLL from a resource
This is a question which comes up frequently.& &How can I use DLLs and
distribute only a single executable?& Well, the real answer is that you should
use an installer, but for this case I needed to have a file that was a &master
copy& of the DLL but was not in fact the DLL.& This was awkward to
accomplish.& For example, I could have had the linker write the file
TheDLL.xxx, which I did originally, but when it came time to implement the
SafeDllSearchMode, I needed to do implicit linking, and the name of the
output file became part of the import record in the executable image.& So I
really had to write the output as TheDLL.dll, but this introduced
problems when I wanted to move it around.& This seemed a good opportunity
to implement the DLL as a resource.
First, I had to create a
dependency in the projects.& The TheDLL project had to be built
before the executable image that contains it.& This is done by selecting
Project&&&Project&Dependencies... which brings up the dialog shown to
the left.& Then, as shown, the LoadLibraryExplorer project is made
dependent on the TheDLL project.
The test application, SafeDllTest, is also made dependent on the build
of TheDLL, because it requires the most recent .lib file be used
to perform the linking of this application.
Next, I had to add the DLL as
a resource.& This was more than a little tricky, because I actually have
two different DLLs I want to include.& The Debug version of the project
should include the Debug version of the DLL, and the Release version of the
project should include the Release version of the DLL.
What I did was to first Import the DLL. Right-click on the project, select
Add&Resource, and the dialog shown to the right will appear.& Click the
Import... button.& A standard file-open dialog will appear.&
What I did was go to the Debug directory, select TheDLL.dll, and click
the Save option.& This will then prompt for a resource type, which I gave
the type &DLL&.& So now I was partway to my solution,
One thing I had to do was deal with the fact that the Import option,
when pointed at the file, makes a copy of the file in the
\res subdirectory of the project.& I did
not want the resource to come from the \res
directory, I wanted it to always go out to the proper directory and get the most
recent copy of the DLL.& So I went to the Properties and edited the
location.& I also added a Condition property to the resource,
indicating that it is included only if the _DEBUG symbol is defined.
Note the three key pieces of
information in the properties shown.& The Condition indicates the
_DEBUG symbol is required to have this resource included.& While it
would have been nice to have been able to use a macro, such as $(OutDir),
to indicate the source of the DLL, macros don't work here (makes you wonder
sometimes about orthogonality), but I had to give a path which included the
Debug mode.&
Having redirected the source
of the resource to its original directory, I had to go into the
\res directory and delete the copy that had been
made during the original import.& Next, I added another resource, which was
the version from the Release directory.& In this case, I changed the
Filename to point to the desired DLL, I added the conditional NDEBUG
(which is defined in the non-debug build), and I also hand-edited the ID
to be the same as the debug DLL's ID.& The result was two different
resources with the same ID, but which are included in the different builds. As
with the first inclusion, I had to go back and delete the file from the
\res subdirectory.
This got the resources into the executable.& Now the problem was how to
get them out.& This was actually straightforward.& To load the DLL
resource, I simply called ::FindResource(AfxGetInstanceHandle(),&MAKEINTRESOURCE(IDR_DLL),&_T(&DLL&))
to obtain an HRSRC handle.& With this resource handle, I could
call ::SizeofResource(AfxGetInstanceHandle(),&rsrc) to find out the size.&
Then a LoadResource to get an HGLOBAL, and a LockResource
to get a pointer to the data.& Then all I had to do was a simple
::CreateFile of the name of the master copy of the DLL (which I called
TheDLL.xxx), and I could do a
::WriteFile on the pointer returned by LockResource for the number of
bytes obtained by SizeofResource, and the DLL prototype comes into
existence.& If you need only the DLL, then you could write the
.dll file directly.
Communicating strings between processes
Another question that comes up frequently is how to communicate data
structures between processes, the most common one being a string value.&
There are a number of possible ways to accomplish this, but WM_COPYDATA
is a fairly straightforward way to handle this.& This mechanism does have
some risks, which I describe in an essay on .& I did a slight variation on this class to support
what I needed to implement this solution.
What I do is launch a child process which has an implicit DLL load to my DLL.&
I then use the techniques that allow the DLL to be placed anywhere in the set of
possible targets, and I call an explicit function in the DLL to perform a
::GetModuleFileName. Now I need to communicate this information back to the
parent.& I could have done a printf, and captured the output via a
named pipe, but the WM_COPYDATA solution gave me an excuse to write this
section of the article.
The WM_COPYDATA message requires a destination window.& I provide
the window handle by passing in, as the first (and only) parameter of the
invocation, the hexadecimal value of the window handle.& Even though this
is just a console application, the full Win32 API is available, and it can
easily do a SendMessage to transmit the message to any window.& Note
that SendMessage is generally contraindicated as a means of inter-process
(hence inter-thread) communication, but WM_COPYDATA is an exception: it
can only be sent via SendMessage, not by the preferred
PostMessage.
Other goodies
Much of what remains is very mundane, but I mention here for those who may be
curious about how to do certain things:
An owner-draw ComboBox that allows me to place checkmarks next to the
loaded DLLs.
The use of a ComboBox that dynamically resizes so that scrolling is not
necessary (scrolling is only necessary if the box can't fit on the screen).
A static control that supports background highlighting.
of a GetLastError code
to a printable CString
that allows various
lines to be highlighted to indicate comments, errors, etc., along with a set
of classes that implement this feature.
The use of my
A printer utility that shows how to print from something other than a
CView (specifically, the contents of the Logging ListBox).
without blocking the GUI thread
The use of
communication intra-process and inter-process
The creation and deletion of subdirectories
The ability to resize the dialog and have some of the controls resize
The ability to limit the minimum size of the resizing so no controls are
The ability to
Many of these techniques seem obvious once you've seen them, but may not be
obvious until you've seen them at least once.& But most of these techniques
were simply &lying around& in my toolbox, easily copied and modified for this
project.& Even so, the project is a modest, under 10K source lines. Of
those lines, I wrote somewhat less than 4000, and even many of those were
written for me by the MFC ClassWizard and AppWizard.& 3700 of those lines
were in the single LoadLibraryExplorerDlg.cpp
file, and the bulk of the remaining lines were in
LoadLibraryExplorerDlg.h.
This project was written under VS.NET 2003 and may or may not work in VS6.
The views expressed in these essays are those of the
author, and in no way represent, nor are they endorsed by, Microsoft.
Send mail to
with questions or comments about this web site.
Copyright (C) 2006 Joseph M. Newcomer/FlounderCraft Ltd.&
All Rights Reserved.
Last modified:
May 14, 2011

我要回帖

更多关于 load application 的文章

 

随机推荐