philsquared
philsquared

Reputation: 22493

Enumerate shared folders on Windows with low privileges

Using C++ (VS2008) I need to be able to enumerate all shared folders on the current machine and get or construct the local and remote names.

We've been using NetShareEnum for this fairly successfully, but have hit a problem where we need to run with a user account with low privileges.

To get the local path using NetShareEnum we need to retrieve at least SHARE_INFO_2 structures - but that requires "Administrator, Power User, Print Operator, or Server Operator group membership".

I've been trying to use WNetOpenEnum and WNetEnumResource instead but I don't seem to be getting the local name back for that for shares either. AFAICS it only enumerates the shares from an external perspective.

So I'd either like help on where I'm going wrong with WNetEnumResource, or a suggestion as to another way of doing this. Any suggestions are much appreciated.

Upvotes: 2

Views: 3307

Answers (2)

MSalters
MSalters

Reputation: 179799

If you have an idea what the local path would be, you can brute-force it by testing: (TODO: make everything Unicode)

// Helper function to make a name unique.
std::string computername()
{
    static std::string name = []() {
        WCHAR buf[MAX_COMPUTERNAME_LENGTH];
        DWORD len = MAX_COMPUTERNAME_LENGTH;
        GetComputerNameEx(ComputerNameNetBIOS, buf, &len);
        return std::string(buf, buf + len);
    }();
    return name;
}

int main()
{
    std::string dir = "C:\\FindThisShare\\";
    // First, create marker
    std::string testfile = computername() + " 038D2B86-7459-417B-9179-90CEECC6EC9D.txt";
    std::ofstream test(dir + testfile);
    test << "This directory holds files from " << computername() 
         << std::endl;
    test.close();

    // Next, find the UNC path holding it.
    BYTE* buf;
    DWORD numEntries;
    NetShareEnum(nullptr, 1, &buf, MAX_PREFERRED_LENGTH, &numEntries,
                 &numEntries, nullptr);
    auto data = reinterpret_cast<SHARE_INFO_1*>(buf);
    std::string retval;
    for (int i = 0; i != numEntries; ++i)
    {
        auto const& entry = data[i];
        std::wstring tmp(entry.shi1_netname);
        std::string share(tmp.begin(), tmp.end());
        std::string uncdir = "\\\\" + computername() + "\\" + share + "\\";
        if (PathFileExistsA((uncdir + testfile).c_str()))
        {
            printf("Exists");
        }
    }
    remove((dir + testfile).c_str());
    NetApiBufferFree(buf);
}

Upvotes: 1

Gabe
Gabe

Reputation: 86718

It sounds like you're specifying RESOURCE_GLOBALNET for the scope, but it's hard to tell what's wrong without seeing your code.

It's hard to help without knowing what you tried and what you got back. For example, what local name are you expecting and what is getting returned? Did you try NetShareEnum with SHARE_INFO_503?

Upvotes: 0

Related Questions