Recent

Author Topic: [Solved] Crash calling Windows API (netapi32.dll)  (Read 4568 times)

ArminLinder

  • Sr. Member
  • ****
  • Posts: 314
  • Keep it simple.
[Solved] Crash calling Windows API (netapi32.dll)
« on: February 24, 2017, 11:30:32 am »
Hi,

I try to make calls to the NetAPI32 Windows networking API. Generally I think I got the translation of the C-Style API calls to Pascal conventions right, I can, for instance, query user infos and such using similar code.

But this call to NetUserGetLocalGroups gives me headaches:

Code: Pascal  [Select][+][-]
  1. implementation
  2.  
  3. {$R *.lfm}
  4.  
  5. uses Windows, CTypes;
  6.  
  7. const
  8.   MAX_PREFERRED_LENGTH = DWORD(-1);
  9.   NERR_SUCCESS = 0;
  10.  
  11. type
  12.   TLocalGroup_Users_Info0 = record
  13.     lgrui0_name: LPWSTR;
  14.   end;
  15.   PTLocalGroup_Users_Info0 = ^TLocalGroup_Users_Info0;
  16.  
  17. function NetUserGetLocalGroups(ServerName, UserName: PWideChar;
  18.   Level: DWORD; var Buffer: Pointer; PrefMaxLen: DWORD;
  19.   var EntriesRead: DWORD; var TotalEntries: DWORD): DWORD;
  20.   stdcall; external 'netapi32.dll';
  21.  
  22. function NetApiBufferFree(Buffer: pointer): DWORD; stdcall;
  23.   external 'netapi32.dll';
  24.  
  25. { TForm1 }
  26.  
  27. procedure TForm1.ButtonLocalGroupsClick(Sender: TObject);
  28.  
  29. var
  30.   dwEntriesRead, dwEntriesTotal: DWORD;
  31.   pBuffer: Pointer;
  32.   pInfo: PTLocalGroup_Users_Info0;
  33.   ServerName,UserName:WideString;
  34.   Result : DWORD;
  35.  
  36. begin
  37.   ListBox1.Clear;
  38.   ServerName := ServerEdit.Text;
  39.   UserName := UserEdit.Text;
  40.   Result := NetUserGetLocalGroups(PWideChar(Servername), PWideChar(UserName), 0, pBuffer, MAX_PREFERRED_LENGTH, dwEntriesRead, dwEntriesTotal);
  41.   If Result = NERR_SUCCESS then
  42.     try
  43.       pInfo := pBuffer;
  44.       while dwEntriesRead > 0 do
  45.       begin
  46.         ListBox1.Items.Add(pInfo^.lgrui0_name);
  47.         Inc(pInfo);
  48.         Dec(dwEntriesRead);
  49.       end;
  50.     finally
  51.       NetAPIBufferFree(pBuffer);
  52.     end
  53.   else
  54.     ListBox1.Items.Add('Error ' + IntToStr(Result));
  55. end;

The call to NetUserGetLocalGroups in the button click handler causes an access violation error (SIGSEV) in samcli!NetUserGetLocalgroups, and I cannot figure out what I possibly have done wrong. There is also plenty of sample code around about this call which looks very similar to mine, I did even try to use some, but all crash the same way.

From forum comments I read, the code has once been working, though 10 years ago. Seems something has changed which breaks the old code?

Anyone knows why this call fails?

Thx

Armin.

« Last Edit: February 24, 2017, 01:15:24 pm by Nimral »
Lazarus 3.3.2 on Windows 7,10,11, Debian 10.8 "Buster", macOS Catalina, macOS BigSur, VMWare Workstation 15, Raspberry Pi

balazsszekely

  • Guest
Re: Crash calling Windows API (netapi32.dll)
« Reply #1 on: February 24, 2017, 12:08:16 pm »
First of all we have a nice unit named jwaWindows. A lot of winapi stuff is declared there, no need to re-delcare variables.
Secondly you missing the fourth parameter(Flags) just after Level. See here: https://msdn.microsoft.com/en-us/library/windows/desktop/aa370655(v=vs.85).aspx
Thirdly it can be done much simpler. Try something like this:
Code: Pascal  [Select][+][-]
  1. uses JwaWindows;
  2.  
  3. function NetUserGetLocalGroups(ServerName, UserName: PWideChar;
  4.   Level, Flags: DWORD; var Buffer: Pointer; PrefMaxLen: DWORD;
  5.   var EntriesRead: DWORD; var TotalEntries: DWORD): DWORD;
  6.   stdcall; external 'netapi32.dll';
  7.  
  8. function NetApiBufferFree(Buffer: pointer): DWORD; stdcall;  external 'netapi32.dll';
  9.  
  10. { TForm1 }
  11.  
  12. procedure TForm1.Button1Click(Sender: TObject);
  13. type
  14.   LocalGroupUsers = array[0..ANYSIZE_ARRAY-1] of LOCALGROUP_USERS_INFO_0;
  15.   PLocalGroupUsers = ^LocalGroupUsers;
  16. var
  17.   dwEntriesRead, dwEntriesTotal: DWORD;
  18.   pBuffer: PLocalGroupUsers;
  19.   I: Integer;
  20.   nErr: integer;
  21.   ServerName,UserName:WideString;
  22.   Result : DWORD;
  23. begin
  24.   ListBox1.Clear;
  25.   ServerName := ServerEdit.Text;
  26.   UserName := UserEdit.Text;
  27.   Result := NetUserGetLocalGroups(PWideChar(Servername), PWideChar(UserName), 0, LG_INCLUDE_INDIRECT, PByte(pBuffer), MAX_PREFERRED_LENGTH, dwEntriesRead, dwEntriesTotal);
  28.   If Result = NERR_SUCCESS then
  29.     try
  30.       for I := 0 to dwEntriesRead - 1 do
  31.         ListBox1.Items.Add(pBuffer^[I].lgrui0_name);
  32.     finally
  33.       NetAPIBufferFree(pBuffer);
  34.     end
  35.   else
  36.     ListBox1.Items.Add('Error ' + IntToStr(Result));
  37. end;

ArminLinder

  • Sr. Member
  • ****
  • Posts: 314
  • Keep it simple.
Re: Crash calling Windows API (netapi32.dll)
« Reply #2 on: February 24, 2017, 12:37:46 pm »
Aaaarg.

Shame on me. I indeed missed the flags parameter, though I went through the call at least a dozen times.

Filled it in, and got success.

Thnx,

Armin.
Lazarus 3.3.2 on Windows 7,10,11, Debian 10.8 "Buster", macOS Catalina, macOS BigSur, VMWare Workstation 15, Raspberry Pi

ArminLinder

  • Sr. Member
  • ****
  • Posts: 314
  • Keep it simple.
Re: [Solved] Crash calling Windows API (netapi32.dll)
« Reply #3 on: February 24, 2017, 02:08:01 pm »
Aaaaarg #2.

Looking deeper into JwaWindows I found it includes a unit JWAlmaccess, which does already contain everything I need to access the Windows network and the local group membership infos specifically.

No need to write the api wrappers for netapi32.dll, they are already there. Only the call parameters differ slightly from the approach above, easy fix:

Code: Pascal  [Select][+][-]
  1. Result := NetUserGetLocalGroups(PWideChar(Servername), PWideChar(UserName), 0, LG_INCLUDE_INDIRECT, PByte(pBuffer), MAX_PREFERRED_LENGTH, @dwEntriesRead, @dwEntriesTotal);

Thanks for sticking my nose into the Jedi library, I guess it is going to be a regular companion for me in the future :-)

Armin.

Lazarus 3.3.2 on Windows 7,10,11, Debian 10.8 "Buster", macOS Catalina, macOS BigSur, VMWare Workstation 15, Raspberry Pi

 

TinyPortal © 2005-2018