SHCreateItemFromParsingName return FILE_NOT_FOUND 指定文件名时

SHCreateItemFromParsingName return FILE_NOT_FOUND when filename specified

我尝试获取文件的 IShellItem,以使用 IFileOperation COM 接口将其从系统目录复制到另一个目录。为此,我必须完全使用 IFileOperation COM 接口。

当我指定完整文件名时 - SHCreateItemFromParsingName() 中的 return 值是 ERROR_FILE_NOT_FOUND,但文件存在于目录中。当我从下面的路径中删除文件名并仅使用文件夹路径时 - 一切似乎都很好,return 值为 S_OK.

//...
CoInitialize(NULL);
//...
WCHAR szSourceDll[MAX_PATH * 2];
wcscpy_s(szSourceDll, MAX_PATH, L"C:\Windows\System32\sysprep\cryptbase.dll");
r = CoCreateInstance(&CLSID_FileOperation, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_INPROC_HANDLER, &IID_IFileOperation, &FileOperation1);
if (r != S_OK) return;
FileOperation1->lpVtbl->SetOperationFlags(FileOperation1, FOF_NOCONFIRMATION | FOFX_NOCOPYHOOKS | FOFX_REQUIREELEVATION);
r = SHCreateItemFromParsingName(szSourceDll, NULL, &IID_IShellItem, &isrc);
//...
CoUninitialize();
//...

为什么用 C 编写的代码不能处理文件名。如何为系统文件夹中的文件创建 IShellItem 实例以复制它?

P.S.

Windows 7 x64,C,Visual Studio 2015,v140 平台工具集,附加依赖项:Msi.lib;Wuguid.lib;ole32.lib;ntdll.lib

P.P.S

它可以正确处理用户目录中的文件...

假设您的应用程序被编译为 32 位应用程序并且 运行 在 64 位 OS 上,找不到文件错误可能是正确的,因为您的应用程序被重定向到 32-位系统目录(%WinDir%\SysWoW64).

In most cases, whenever a 32-bit application attempts to access %windir%\System32, %windir%\lastgood\system32, or %windir%\regedit.exe, the access is redirected to an architecture-specific path.

有关详细信息,请参阅 MSDN 上的 File System Redirector

您可以暂时关闭线程中的重定向,但在调用 shell 函数时这样做并不安全,仅在 kernel32 中起作用。如果您在内部调用的 API 使用 LoadLibrary and/or COM,则 API 可能会失败,因为在禁用重定向时它将无法从 system32 加载。

您还可以使用 %WinDir%\SysNative 后门访问本机 system32 目录。这仅适用于 64 位 Vista+ 上的 32 位应用程序,因此您必须进行一些版本检测。