Thursday, February 18, 2010

Unable to load .DLLs due to "Unable To Locate Component" with semi-colon path

I recently worked on a nasty problem which I couldn’t find anyone solved. I hope this helps someone who hits the same problem.

PROBLEM DESCRIPTION

PROBLEM
A process fails to load .DLL file due to the error c0000135 (STATUS_DLL_NOT_FOUND) if the .DLL file path contains semi colon(;).
This problem occurs if you meet all of the following conditions:
  1. The execution file (.EXE) and .DLL file are placed in the same path
  2. The file path of the .DLL contains semi colon (;).
  3. .EXE loads the DLL
  4. The .EXE file is executed from the different execution path than the file path of the .EXE file.
ERROR MESSAGE
Unable To Locate Component: This application has failed to start because xxx.dll was not found. Re-installing the application may fix the problem.
Notes: A dialog shows up even if you execute the process as a console application.
REPRO
Download DllLoadFailureTest.zip from the link, extract it and run Repro.bat if you want.
RESOLUTION
Do NOT use “;” as a file path.

INVESTIGATION

I attached a debugger when an error message dialog showed up before closing it.
0:000> du 10000
00010000  "=C:=C:\WINDOWS\system32"   // execution path = %WINDIR%\SYSTEM32

0:000> lmvm DllLoadFailureTest
    Image path: C:\DllLoadFailure;Test\DllLoadFailureTest.exe   // execution file

0:000> kbn4
# ChildEBP RetAddr  Args to Child             
00 0012f740 7c827779 7c84b905 c0000135 00000002 ntdll!KiFastSystemCallRet
01 0012f744 7c84b905 c0000135 00000002 00000003 ntdll!ZwRaiseHardError+0xc  // STATUS_DLL_NOT_FOUND
02 0012f838 7c83304f 00020498 0012f884 7ffdfc00 ntdll!LdrpMapDll+0x1c4      // DLL path, DLL name
03 0012fa9c 7c832fa5 00020498 00402354 0012fac0 ntdll!LdrpLoadImportModule+0x17c

0:000> du poi(00020498)
00020498  "C:\DllLoadFailure;Test;C:\WINDOW"    // DLL paths are separated with “;”
000204d8  "S\system32;C:\WINDOWS\system;C:\"
00020518  "WINDOWS;.;C:\WINDOWS\system32;C:"    // Current directory (execution path).
00020558  "\WINDOWS;C:\WINDOWS\System32\Wbe"

0:000> du poi(7ffdfc00)
7ffdfc00  "MyDll.dll"   // DLL being loaded. The full path is C:\DllLoadFailure;Test\MyDLL.dll
The DLL path has a problem. C:\DllLoadFailure;Test got to be separated into  C:\DllLoadFailure and Test because paths must be separated with “;”. Therefore Windows doesn’t understand the path ” C:\DllLoadFailure;Test”. When you execute a process from the path where .EXE is located, in other words, the execution path and .EXE file path is the same, Windows loads the DLL from current directory (.) using relative path.
You better not (actually shouldn’t) make a path which contains “;” even though Windows allows.

No comments:

Post a Comment