Friday, July 31, 2009

WCF web service failed with 0x8007007E

The WCF web service I worked on failed with the following error message when I tried to launch it from IIS:

The specified module could not be found. (Exception from HRESULT: 0x8007007E).

From the previous encounter, I was pretty sure that it must have something to do with WrapperUtilAPI.dll. The library written in managed C++ serves as the bridge between the managed and unmanaged code.

Since the web service is in the managed code, I first tried the Fusion log viewer to see whether there had been any assembly binding error. Except that the web service module itself did not show in the log viewer, there had been no assembly binding error for all other dependent modules, such as WrapperUtilAPI.dll:

The operation was successful.
Bind result: hr = 0x0. The operation completed successfully.


It seemed that the culprit was from the unmanaged code. Then I used Process Monitor to record the activities from aspnet_wp.exe when I tried to launch the web service through it.

For a DLL to load successfully, the following operation sequence should take place,

QueryOpen C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\wsftp.webservicehost\89b3cfc4\ab5fbeff\assembly\dl3\f9b47a83\007d695c_3011ca01\ftpaccess.dll NAME NOT FOUND
QueryOpen C:\WINDOWS\system32\ftpaccess.dll NAME NOT FOUND
QueryOpen C:\WINDOWS\system\ftpaccess.dll NAME NOT FOUND
QueryOpen C:\WINDOWS\ftpaccess.dll NAME NOT FOUND
QueryOpen C:\WINDOWS\system32\ftpaccess.dll NAME NOT FOUND
QueryOpen C:\Perl\site\bin\ftpaccess.dll NAME NOT FOUND
QueryOpen C:\Perl\bin\ftpaccess.dll NAME NOT FOUND
QueryOpen C:\WINDOWS\system32\ftpaccess.dll NAME NOT FOUND
QueryOpen C:\WINDOWS\ftpaccess.dll NAME NOT FOUND
QueryOpen C:\WINDOWS\system32\wbem\ftpaccess.dll NAME NOT FOUND
QueryOpen C:\Program Files\Microsoft SQL Server\90\Tools\Binn\ftpaccess.dll NAME NOT FOUND
QueryOpen C:\Program Files\Ipswitch\Common\ftpaccess.dll SUCCESS
QueryOpen C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\wsftp.webservicehost\89b3cfc4\ab5fbeff\assembly\dl3\f9b47a83\007d695c_3011ca01\ftpaccess.dll NAME NOT FOUND
QueryOpen C:\WINDOWS\system32\ftpaccess.dll NAME NOT FOUND
QueryOpen C:\WINDOWS\system\ftpaccess.dll NAME NOT FOUND
QueryOpen C:\WINDOWS\ftpaccess.dll NAME NOT FOUND
QueryOpen C:\WINDOWS\system32\ftpaccess.dll NAME NOT FOUND
QueryOpen C:\Perl\site\bin\ftpaccess.dll NAME NOT FOUND
QueryOpen C:\Perl\bin\ftpaccess.dll NAME NOT FOUND
QueryOpen C:\WINDOWS\system32\ftpaccess.dll NAME NOT FOUND
QueryOpen C:\WINDOWS\ftpaccess.dll NAME NOT FOUND
QueryOpen C:\WINDOWS\system32\wbem\ftpaccess.dll NAME NOT FOUND
QueryOpen C:\Program Files\Microsoft SQL Server\90\Tools\Binn\ftpaccess.dll NAME NOT FOUND
QueryOpen C:\Program Files\Ipswitch\Common\ftpaccess.dll SUCCESS
CreateFile C:\Program Files\Ipswitch\Common\ftpaccess.dll SUCCESS
CloseFile C:\Program Files\Ipswitch\Common\ftpaccess.dll SUCCESS
Load Image C:\Program Files\Ipswitch\Common\ftpaccess.dll SUCCESS

QueryOpen will try to locate a module using the DLL search path.

While looking through the log from Process Monitor, I noticed the following lines,

QueryOpen C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\wsftp.webservicehost\89b3cfc4\ab5fbeff\assembly\dl3\f9b47a83\007d695c_3011ca01\zlib1.dll NAME NOT FOUND
QueryOpen C:\WINDOWS\system32\zlib1.dll NAME NOT FOUND
QueryOpen C:\WINDOWS\system\zlib1.dll NAME NOT FOUND
QueryOpen C:\WINDOWS\zlib1.dll NAME NOT FOUND
QueryOpen C:\WINDOWS\system32\zlib1.dll NAME NOT FOUND
QueryOpen C:\Perl\site\bin\zlib1.dll NAME NOT FOUND
QueryOpen C:\Perl\bin\zlib1.dll NAME NOT FOUND
QueryOpen C:\WINDOWS\system32\zlib1.dll NAME NOT FOUND
QueryOpen C:\WINDOWS\zlib1.dll NAME NOT FOUND
QueryOpen C:\WINDOWS\system32\wbem\zlib1.dll NAME NOT FOUND
QueryOpen C:\Program Files\Microsoft SQL Server\90\Tools\Binn\zlib1.dll NAME NOT FOUND
QueryOpen C:\Program Files\Ipswitch\Common\zlib1.dll NAME NOT FOUND
QueryOpen C:\Program Files\Support Tools\zlib1.dll NAME NOT FOUND
QueryOpen C:\Program Files\Ipswitch\Common\zlib1.dll NAME NOT FOUND
QueryOpen C:\MinGW\bin\zlib1.dll NAME NOT FOUND
QueryOpen C:\Program Files\QuickTime\QTSystem\zlib1.dll NAME NOT FOUND
QueryOpen C:\WINDOWS\system32\windowspowershell\v1.0\zlib1.dll NAME NOT FOUND
QueryOpen C:\WINDOWS\WinSxS\x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.30729.1_x-ww_6f74963e\zlib1.dll NAME NOT FOUND
CloseFile C:\WINDOWS\WinSxS\x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.30729.1_x-ww_6f74963e SUCCESS
CloseFile C:\WINDOWS\WinSxS\x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.30729.1_x-ww_6f74963e SUCCESS
CloseFile C:\WINDOWS\WinSxS\x86_Microsoft.VC90.CRT_1fc8b3b9a1e18e3b_9.0.30729.1_x-ww_6f74963e SUCCESS
CloseFile C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\wsftp.webservicehost\89b3cfc4\ab5fbeff\assembly\dl3\f9b47a83\007d695c_3011ca01\WrapperUtilAPI.DLL SUCCESS

It seemed that the application tried to load zlib1.dll. However, the module could not be found in the DLL search path. Therefore, instead of loading zlib1.dll, the application closed WrapperUtilAPI.dll, which had been loaded early.

Since I was pretty sure that zlib1.dll had to be loaded so that WrapperUtilAPI.dll could be loaded successfully, and its location was not in the PATH environment variable and the DLL search path. So at the point, the root cause seemed to be the failure to load zlib1.dll. Then I copied it to the location on the DLL search path, the web service could be launched from IIS.

Wednesday, July 29, 2009

How to Bind to a custom App.Config file?

One of questions I ever had when I worked on the ISAPI extension was where to store the configuration file. The ISAPI extension is in unmanaged code hosted in IIS via dllhost.exe. It will interact with the backend managed code by COM interop. The manged code will create WCF proxies to communicate to the WCF web service. Therefore, the configuration file will be required by the WCF code to load the information regarding to the contract, binding, endpoint, and client behavior. A naive solution is to use dllhost.exe.config in the Windows system directory. Fortunately, the article by Ohad -- Binding to a custom App.Config file provides a useful information to solve the problem.

Wednesday, July 22, 2009

Build and debug ISAPI extension

I have built and debugged an ISAPI extension DLL before. However, it still gave me a little bit hard time today when I tried to debug an ISAPI extension DLL which I built by myself. The article by Mehdi Mousav -- What is an ISAPI Extension? provies a pretty good coverage on this topic. The setup of ISAP extension DLL in IIS is straightforward -- copy the DLL to the folder which can be accessed from the URL, such as http://Domain/DLLPath. For the author of the ISAPI extension DLL, one caveat is the module definition file (.def). The ISAPI extension DLL needs to be built with it; otherwise, the ISAPI extension APIs will not be visible to an IIS worker process.

Tuesday, July 7, 2009

Obtain stack limit of WOW64 process

A WOW64 process is a 32-bit process running on x64 Windows. The article -- Raw Stack Dump of WOW64 Process by Dmitry Vostokov explains several ways to retrieve the stack limit of a thread from TEB for a WOW64 process.

Hunt for parameters of a function

The article -- Hunting for a Driver by Dmitry Vostokov illustrates a useful approach to discover the parameters of a function.