LoadLibraryW and POSIX path separator

試著忘記壹切 提交于 2020-08-09 05:43:30

问题


The MSDN documentation for LoadLibrary warns not to use normal Unix slash "/":

When specifying a path, be sure to use backslashes (\), not forward slashes (/).

I couldn't find any problems using either forward slashes or backslashes (or both) when calling this API. I tried the following pathnames:

c:/foo/bar/baz.dll
/foo/bar/baz.dll
c:/foo/bar\\baz.dll
/foo/bar\\baz.dll
./bar/baz.dll

All combinations worked as expected. Why does the MSDN recommend against using forward slashes as path separators?

Edit:

Regarding UNC Names, it works perfectly well with "//127.0.0.1/c$/foo/bar/baz.dll" as well.

And yes if you add "\?\" it does not load the library but _wfopen would also fail to open file. How LoadLibraryW is different from any other Windows API accepting/not-accepting forward slashes? Why there are explicit warning regarding LoadLibraryW and not CreateFileW.

CreateFile: https://msdn.microsoft.com/en-us/library/windows/desktop/aa363858(v=vs.85).aspx

The name of the file or device to be created or opened. You may use either forward slashes (/) or backslashes () in this name.

LoadLibrary: https://msdn.microsoft.com/en-us/library/windows/desktop/ms684175(v=vs.85).aspx

When specifying a path, be sure to use backslashes (), not forward slashes (/).

Is there some other pitfails that may cause LoadLibrary to fail when forward slashes (/) are used, while other Windows API would accept forward slashes without any issue?


回答1:


File I/O in the Windows API converts forward slashes ("/") to backslashes ("\"), before passing the request to the native API. The native API expects NT-style names. No conversion is performed when the pathname is prefixed with "\\?\". Sometimes you do not have control over whether or not this prefix is present (e.g. when retrieving the base path using the Windows API).

In short: Using the native path separator is the safe solution. Violating the contract and using a forward slash may suddenly stop working.

Complete information is documented in the MSDN at Naming Files, Paths, and Namespaces.




回答2:


The reason is so the programmer does not get into strange problems later on. The Windows API is vast and lots of combinations are expected to work. By outlawing some cases they make their life easier.

But I gather you want this particular case. Here it goes. The Windows loader needs to maintain its own databases of modules and paths, some of this is in fact exposed in the API, so at some level they have to choose a canonical representation and then they can forget about the details how the system got the DLL in the first place. This is more so in the loader which in fact an NT-layer component, not a Win32 layer component. So paths going in from Win32 get the compat treatment you notice, but paths going out go from NT-native to Win32 via a canonical transformation.

Take this example

#include "stdafx.h"

const wchar_t name[] = L"c:/windows/system32/atl.dll";

int main() {
  HMODULE mod1 = ::LoadLibrary(name);

  wchar_t lo_name[512];
  GetModuleFileName(mod1, lo_name, 512);
  wprintf(L"%s - %s", name, lo_name);

  return 0;
}

As you can see it prints different strings. Now imagine developer might decide that they need to free modules based on name equality or some weird scheme. It does not work.

bool FreeLibByName(HMODULE mod, const wchar_t* name) {
  wchar_t lo_name[512];
  GetModuleFileName(mod, lo_name, 512);
  if (wcscmp(name, lo_name) != 0) {
    return false;
  }
  FreeLibrary(mod);
  return true;
}

If you have not been programming Windows for long that function does not even look that strange.

But there's more: https://msdn.microsoft.com/en-us/library/windows/desktop/ms683196(v=vs.85).aspx

To retrieve the base name of a module in the current process, use the GetModuleFileName function to retrieve the full module name and then use a function call such as strrchr(szmodulename, '\') to scan to the beginning of the base name within the module name string. This is more efficient and more reliable than calling GetModuleBaseName with a handle to the current process.

MSDN is telling programmers 'best practices' that assume backslash, imagine if the original path representation in LoadLibrary() had been stored? makes for some messy code here.



来源:https://stackoverflow.com/questions/34708138/loadlibraryw-and-posix-path-separator

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!