c++ – Copy to std::vector and destroy original data

Question:

I am trying to list the connections to shared resources. I would like to return a std::vector with this information but it seems that when I call NetApiBufferFree this information is eliminated and I don't understand why since in theory I copy the content, but it is clear that something is wrong.

Here I leave the function to see if you can help me.

    const std::vector<USE_INFO_2>
    getConnections2shared() {
        typedef std::unique_ptr<USE_INFO_2, std::function<void(USE_INFO_2 *)> > USE_INFO_2_uptr_type;

        NET_API_STATUS result;
        DWORD EntriesRead, TotalEntries;
        USE_INFO_2_uptr_type uptrinfo(nullptr, [](USE_INFO_2 *f) {
            NetApiBufferFree(static_cast<LPVOID> (f));
        });
        USE_INFO_2 * puinfo;
        std::vector<USE_INFO_2> _ret;

        if ((result = NetUseEnum(
                NULL,
                2,
                reinterpret_cast<LPBYTE*> (&puinfo),
                MAX_PREFERRED_LENGTH,
                &EntriesRead,
                &TotalEntries,
                NULL
                )) == NERR_Success) {
            uptrinfo.reset(puinfo);

            _ret.insert(_ret.end(), puinfo, &puinfo[TotalEntries]);

            /* Tampoco funciona así */    
            //_ret.resize(TotalEntries);
            //memcpy(&_ret[0], puinfo, TotalEntries * sizeof (USE_INFO_2));
        }

        /* Aquí la información es mostrada correcta*/
        for (USE_INFO_2 ui2 : _ret) {
            std::wcout << ":" << ui2.ui2_remote << std::endl;
        }
        return _ret;
    }

And I intend to use it like this:

const std::vector<USE_INFO_2> connections = getConnections2shared();

But once NetApiBufferFree is called the vector content gets corrupted. Note that within the function, it correctly displays the information. I have tried removing the call to NetApiBufferFree and then the behavior outside the function is as expected.

Any ideas?

Thanks!

Answer:

It is very normal for you to fail. Let's review USE_INFO_2 :

typedef struct _USE_INFO_2 {
  USE_INFO_1 ui2_useinfo;
  wchar_t* ui2_username;
  wchar_t* ui2_domainname;
 } USE_INFO_2,

ui2_useinfo: A pointer to the USE_INFO_1 (section 2.2.5.22) structure entries returned by the method.

ui2_username: A pointer to a string that contains the name of the user who initiated the connection.

ui2_domainname: A pointer to a string that contains the domain name of the remote resource.

Y ahora, USE_INFO_1:

typedef struct _USE_INFO_1 {
  wchar_t* ui1_local;
  wchar_t* ui1_remote;
  wchar_t* ui1_password;
  long ui1_status;
  unsigned long ui1_asg_type;
  unsigned long ui1_refcount;
  unsigned long ui1_usecount;
 } USE_INFO_1,

As you can see, 3/4 of the same: more pointers.

By themselves, those structures only contain pointers , which become invalid as soon as you call NetApiBufferFree( ) .

You have several options. Personally, I would use my own MyUseInfo2 class with a constructor that takes care of copying the important data:

example:

struct MyUseInfo {
  std::wstring local;
  std::wstring remote;
  std::wstring password;
  long status;
  ...
  std::wstring user;
  std::wstring domain;

  MyUseInfo( USE_INFO_2 * ) { ... }
};

And then you could easily use it in your code, by changing your std::vector<USE_INFO_2> to std::vector< MyUseInfo > .

Scroll to Top