没有 SMBv1 的 WINAPI 网络发现

WINAPI Network Discovery without SMBv1

我需要获取本地网络上可用共享文件夹的列表,以及它们在文件资源管理器的“网络”选项卡中的显示方式。早些时候,我使用 NetServerEnum/NetShareEnum 函数的组合来获取它,但它们使用的是 SMBv1 协议,该协议现在在 windows 中默认禁用,所以现在我从 NetServerEnum 收到错误 1231。但是文件资源管理器仍然可以获取此列表。我尝试使用 Process Monitor 来确定它使用哪个 API,但失败了。那么,有没有什么方法可以在不使用需要 SMBv1 的 API 的情况下获取本地网络中的可用共享文件夹列表?

您可以使用windows shell api 并使用FOLDERID_NetworkFolder 得到“network”的KNOWNFOLDERID

以下示例可以获取“网络”文件夹中的文件夹、非文件夹和隐藏项目。

#include <windows.h>
#include <Shobjidl.h>
#include <Shlobj.h>
#include <iostream>
void wmain(int argc, TCHAR* lpszArgv[])
{
    IShellItem* pShellItem;
    IEnumShellItems* pShellEnum = NULL;
    HRESULT hr = S_OK;
    hr = CoInitialize(NULL);
    if (FAILED(hr))
    {
        printf("CoInitialize error, %x\n", hr);
        return;
    }

    hr = SHGetKnownFolderItem(FOLDERID_NetworkFolder, KF_FLAG_DEFAULT, NULL, IID_PPV_ARGS(&pShellItem));
    if (FAILED(hr))
    {
        printf("SHGetKnownFolderItem error, %x\n", hr);
        return;
    }

    hr = pShellItem->BindToHandler(nullptr, BHID_EnumItems, IID_PPV_ARGS(&pShellEnum));
    if (FAILED(hr))
    {
        printf("BindToHandler error, %x\n", hr);
        return;
    }

    do {
        IShellItem* pItem;
        LPWSTR szName = NULL;

        hr = pShellEnum->Next(1, &pItem, nullptr);
        if (hr == S_OK && pItem)
        {
            HRESULT hres = pItem->GetDisplayName(SIGDN_NORMALDISPLAY, &szName);
            std::wcout << szName << std::endl;
            CoTaskMemFree(szName);
        }
    } while (hr == S_OK);

    CoUninitialize();

}