In a program, you want to verify that the user's input information is correct based on the IP address, domain name, or computer name provided by the user. However, this information is usually vague, some people may not even know what the computer name is, so how can we provide a quick channel to implement such authentication information, or just like sqlserver, how can I log on through domain authentication? This is related to what I want to talk about today. If I can get information in the domain by default through some APIs, I can implement similar functions.
The following describes the implementation:
Unit unit1;
Interface
Uses
Windows, sysutils, variants, stdctrls, extctrls, forms, classes, controls;
Type
Tmainfrom = Class (tform)
Private
Function getlocalhostip (const amachine: string): string;
Function getmacaddresses (const amachine: string): string;
Function getpcname: string;
Function getuseranddomainfrompid (aprocesshandle: thandle;
Out adomain, auser: string): Boolean;
End;
Implementation
{$ R *. dfm}
Uses
Nb30, Winsock;
Const
ConHostIpFmt = '% d. % d ';
{TMainFrom}
Function TMainFrom. GetLocalHostIp (const AMachine: string): string;
Var
PHost: PHostEnt;
StrName: string;
NLength: Integer;
CData: TWSAData;
Begin
WSAStartup (2, cData );
Try
Result: = '';
StrName: = AMachine;
NLength: = StrLen (PChar (strName ));
SetLength (strName, nLength );
PHost: = GetHostByName (PChar (strName ));
If phost = nil then
Exit;
With phost ^ do
Result: = format (conhostipfmt, [byte (h_addr ^ [0]), byte (h_addr ^ [1]),
Byte (h_addr ^ [2]), byte (h_addr ^ [3]);
Finally
Wsacleanup;
End;
End;
Function tmainfrom. getmacaddresses (const amachine: string): string;
Function adaptertostring (adapter: pchar): string;
Begin
Result: = format ('% 2.2x-% 2.2x-% 2.2x-% 2.2x-% 2.2x-% 2.2x ',
[INTEGER (adapter [0]), INTEGER (adapter [1]),
INTEGER (adapter [2]), INTEGER (adapter [3]),
INTEGER (adapter [4]), INTEGER (adapter [5]);
End;
Type
Astat = packed record
Adapt: tadapterstatus;
Namebuff: array [0 .. 29] of tnamebuffer;
End;
VaR
NCB: tncb;
Enum: tlanaenum;
I, L, namelen: integer;
Adapter: astat;
Machinename: string;
Begin
Result: = '';
Machinename: = uppercase (amachine );
If machinename = ''then
Machinename: = '*';
Namelen: = length (machinename );
L: = ncbnamsz-namelen;
If l> 0 then
Begin
SetLength (MachineName, NCBNAMSZ );
FillChar (MachineName [NameLen + 1], L ,'');
End;
{
From Junior/RO in NG: Microsoft's implementation limits NETBIOS names to 15 characters
}
MachineName [NCBNAMSZ]: = #0;
FillChar (NCB, SizeOf (NCB), #0 );
NCB. ncb_command: = Char (NCBENUM );
NCB. ncb_buffer: = Pointer (@ Enum );
NCB. ncb_length: = SizeOf (Enum );
If NetBios (@ NCB) <> Char (NRC_GOODRET) then
Exit;
For I: = 0 to Ord (Enum. Length)-1 do
Begin
FillChar (NCB, SizeOf (NCB), #0 );
NCB. ncb_command: = Char (NCBRESET );
NCB. ncb_lana_num: = Enum. lana [I];
If NetBios (@ NCB) = Char (NRC_GOODRET) then
Begin
FillChar (NCB, SizeOf (NCB), #0 );
NCB. ncb_command: = Char (NCBASTAT );
NCB. ncb_lana_num: = Enum. lana [I];
Move (MachineName [1], NCB. ncb_callname, SizeOf (NCB. ncb_callname ));
NCB. ncb_buffer: = PChar (@ Adapter );
NCB. ncb_length: = SizeOf (Adapter );
If NetBios (@ NCB) = Char (NRC_GOODRET) then
Result: = AdapterToString (PChar (@ Adapter. adapt ));
End;
End;
End;
Function tmainfrom. getpcname: string;
VaR
Nsize: Cardinal;
Pbuffer: array [0 .. max_path-1] of char;
Begin
Nsize: = max_path;
If getcomputername (pbuffer, nsize) then
Result: = strpas (pbuffer)
Else result: = '';
End;
Function tmainfrom. getuseranddomainfrompid (aprocesshandle: thandle;
Out adomain, auser: string): Boolean;
Type
Ptoken_user = ^ token_user;
_ Token_user = record
Auser: tsidandattributes;
End;
Token_user = _ token_user;
VaR
Htoken: thandle;
Cbbuf: Cardinal;
Ptiuser: ptoken_user;
Snu: sid_name_use;
Nusersize, ndomainsize: DWORD;
Bsuccess: Boolean;
Begin
Result: = false;
If openprocesstoken (aprocesshandle, token_query, htoken) then
Try
Bsuccess: = gettokeninformation (htoken, tokenuser, nil, 0, cbbuf );
Ptiuser: = nil;
While (not bsuccess) and (getlasterror = error_insufficient_buffer) Do
Begin
Reallocmem (ptiuser, cbbuf );
Bsuccess: = gettokeninformation (htoken, tokenuser, ptiuser, cbbuf, cbbuf );
End;
If not bsuccess then
Exit;
NUserSize: = 0;
NDomainSize: = 0;
LookupAccountSid (nil, ptiUser. AUser. Sid, nil, nUserSize, nil, nDomainSize, snu );
If (nUserSize <> 0) and (nDomainSize <> 0) then
Begin
SetLength (AUser, nUserSize );
SetLength (ADomain, nDomainSize );
If LookupAccountSid (nil, ptiUser. AUser. Sid, PChar (AUser), nUserSize,
PChar (ADomain), nDomainSize, snu) then
Begin
Result: = True;
AUser: = StrPas (PChar (AUser ));
ADomain: = StrPas (PChar (ADomain ));
End;
End;
If bSuccess then
FreeMem (ptiUser );
Finally
CloseHandle (hToken );
End;
End;
End.
Now you can get the computer name and the IP address, Mac address, and domain name through the computer name.
This program is not only used on the local machine, but also can pass a specified computer name to obtain relevant information. Note that the domain name is obtained through the current process information.