<?xml version='1.0' encoding="utf-8"?>
      <rss version='2.0'>
      <channel>
      <title>Форум на Исходниках.RU</title>
      <link>https://forum.sources.ru</link>
      <description>Форум на Исходниках.RU</description>
      <generator>Форум на Исходниках.RU</generator>
  	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=77960&amp;view=findpost&amp;p=560802</guid>
        <pubDate>Thu, 30 Dec 2004 10:32:21 +0000</pubDate>
        <title>Получение информации по IP</title>
        <link>https://forum.sources.ru/index.php?showtopic=77960&amp;view=findpost&amp;p=560802</link>
        <description><![CDATA[Rouse_: <div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">// Демонстрационная программа получения информации о компьютере</div><div class="code_line">// на основе IP адреса</div><div class="code_line">// Автор: Александр (Rouse_) Багель</div><div class="code_line">// 30 декабря 2004 </div><div class="code_line">// =============================================================</div><div class="code_line">// Специально для FAQ сайта Мастера Дельфи и Исходники.RU</div><div class="code_line">// http://www.delphimaster.ru</div><div class="code_line">// http://forum.sources.ru</div><div class="code_line">&nbsp;</div><div class="code_line">// Windows9x, Windows Millenium не поддерживются </div><div class="code_line">&nbsp;</div><div class="code_line">// Примечание: Я не любитель венгерской нотации в отношении переменных</div><div class="code_line">// и давно выработал собственный, удобный для меня, стиль написания кода,</div><div class="code_line">// (да и начальство не против :) поэтому не судить строго ;)</div><div class="code_line">&nbsp;</div><div class="code_line">unit uMain;</div><div class="code_line">&nbsp;</div><div class="code_line">{$DEFINE RUS}</div><div class="code_line">&nbsp;</div><div class="code_line">interface</div><div class="code_line">&nbsp;</div><div class="code_line">uses</div><div class="code_line">&nbsp;&nbsp;Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,</div><div class="code_line">&nbsp;&nbsp;Dialogs, StdCtrls, ComCtrls, CommCtrl, Winsock;</div><div class="code_line">&nbsp;</div><div class="code_line">const</div><div class="code_line">&nbsp;&nbsp;{$IFDEF RUS}</div><div class="code_line">&nbsp;&nbsp; &nbsp;RES_UNKNOWN = &#39;Неизвестно&#39;;</div><div class="code_line">&nbsp;&nbsp; &nbsp;RES_IP &nbsp; &nbsp; &nbsp;= &#39;IP адрес: &#39;;</div><div class="code_line">&nbsp;&nbsp; &nbsp;RES_CMP &nbsp; &nbsp; = &#39;Имя компьютера: &#39;;</div><div class="code_line">&nbsp;&nbsp; &nbsp;RES_USR &nbsp; &nbsp; = &#39;Имя пользователя: &#39;;</div><div class="code_line">&nbsp;&nbsp; &nbsp;RES_DOM &nbsp; &nbsp; = &#39;Домен: &#39;;</div><div class="code_line">&nbsp;&nbsp; &nbsp;RES_SER &nbsp; &nbsp; = &#39;Сервер домена: &#39;;</div><div class="code_line">&nbsp;&nbsp; &nbsp;RES_COM &nbsp; &nbsp; = &#39;Коментарий: &#39;;</div><div class="code_line">&nbsp;&nbsp; &nbsp;RES_PROV &nbsp; &nbsp;= &#39;Провайдер: &#39;;</div><div class="code_line">&nbsp;&nbsp; &nbsp;RES_GRP &nbsp; &nbsp; = &#39;Группы: &#39;;</div><div class="code_line">&nbsp;&nbsp; &nbsp;RES_MAC &nbsp; &nbsp; = &#39;MAC адресс: &#39;;</div><div class="code_line">&nbsp;&nbsp; &nbsp;RES_SHARES &nbsp;= &#39;Доступные ресурсы: &#39;;</div><div class="code_line">&nbsp;&nbsp; &nbsp;RES_TIME &nbsp; &nbsp;= &#39;Времени затрачено: &#39;;</div><div class="code_line">&nbsp;&nbsp; &nbsp;RES_COM_NO &nbsp;= &#39;Отсутствует&#39;;</div><div class="code_line">&nbsp;&nbsp;{$ELSE}</div><div class="code_line">&nbsp;&nbsp; &nbsp;RES_UNKNOWN = &#39;Unknown&#39;;</div><div class="code_line">&nbsp;&nbsp; &nbsp;RES_IP &nbsp; &nbsp; &nbsp;= &#39;IP adress: &#39;;</div><div class="code_line">&nbsp;&nbsp; &nbsp;RES_CMP &nbsp; &nbsp; = &#39;Computer name: &#39;;</div><div class="code_line">&nbsp;&nbsp; &nbsp;RES_USR &nbsp; &nbsp; = &#39;User name: &#39;;</div><div class="code_line">&nbsp;&nbsp; &nbsp;RES_DOM &nbsp; &nbsp; = &#39;Domen: &#39;;</div><div class="code_line">&nbsp;&nbsp; &nbsp;RES_SER &nbsp; &nbsp; = &#39;Domen server: &#39;;</div><div class="code_line">&nbsp;&nbsp; &nbsp;RES_COM &nbsp; &nbsp; = &#39;Comment: &#39;;</div><div class="code_line">&nbsp;&nbsp; &nbsp;RES_PROV &nbsp; &nbsp;= &#39;Provider: &#39;;</div><div class="code_line">&nbsp;&nbsp; &nbsp;RES_GRP &nbsp; &nbsp; = &#39;Groups: &#39;;</div><div class="code_line">&nbsp;&nbsp; &nbsp;RES_MAC &nbsp; &nbsp; = &#39;MAC adress: &#39;;</div><div class="code_line">&nbsp;&nbsp; &nbsp;RES_SHARES &nbsp;= &#39;Available shares: &#39;;</div><div class="code_line">&nbsp;&nbsp; &nbsp;RES_TIME &nbsp; &nbsp;= &#39;Expended time: &#39;;</div><div class="code_line">&nbsp;&nbsp; &nbsp;RES_COM_NO &nbsp;= &#39;Absent&#39;;</div><div class="code_line">&nbsp;&nbsp;{$ENDIF}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;WSA_TYPE = 1; //2;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Для работы с ARP (Address Resolution Protocol) таблицей</div><div class="code_line">&nbsp;&nbsp;IPHLPAPI = &#39;IPHLPAPI.DLL&#39;;</div><div class="code_line">&nbsp;&nbsp;MAX_ADAPTER_ADDRESS_LENGTH = 7;</div><div class="code_line">&nbsp;</div><div class="code_line">type</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;LMSTR = LPWSTR;</div><div class="code_line">&nbsp;&nbsp;NET_API_STATUS = DWORD;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Следующие три типа используются для работы с Iphlpapi.dll</div><div class="code_line">&nbsp;&nbsp;// Выдрал из Iphlpapi.h</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Так будет выглядеть МАС</div><div class="code_line">&nbsp;&nbsp;TMacAddress = array[0..MAX_ADAPTER_ADDRESS_LENGTH] of byte;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Это структура для единичного запроса</div><div class="code_line">&nbsp;&nbsp;TMibIPNetRow = packed record</div><div class="code_line">&nbsp;&nbsp; &nbsp;dwIndex &nbsp; &nbsp; &nbsp; &nbsp; : DWORD;</div><div class="code_line">&nbsp;&nbsp; &nbsp;dwPhysAddrLen &nbsp; : DWORD;</div><div class="code_line">&nbsp;&nbsp; &nbsp;bPhysAddr &nbsp; &nbsp; &nbsp; : TMACAddress; &nbsp;// Вот здесь и лежит МАС!!!</div><div class="code_line">&nbsp;&nbsp; &nbsp;dwAddr &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: DWORD;</div><div class="code_line">&nbsp;&nbsp; &nbsp;dwType &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: DWORD;</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Как и в статье не будем выделять память динамически,</div><div class="code_line">&nbsp;&nbsp;// а сразу создадим массив... (хотя, чесно говоря, это не правильно,</div><div class="code_line">&nbsp;&nbsp;// но я иду простым путем :)</div><div class="code_line">&nbsp;&nbsp;TMibIPNetRowArray = array [0..512] of TMibIPNetRow;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// А это, как и во всей библиотеке, такая вот...</div><div class="code_line">&nbsp;&nbsp;// запрашиваемая структура (в моей статье уже видел пример...)</div><div class="code_line">&nbsp;&nbsp;PTMibIPNetTable = ^TMibIPNetTable;</div><div class="code_line">&nbsp;&nbsp;TMibIPNetTable = packed record</div><div class="code_line">&nbsp;&nbsp; &nbsp;dwNumEntries &nbsp; &nbsp;: DWORD;</div><div class="code_line">&nbsp;&nbsp; &nbsp;Table: TMibIPNetRowArray;</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Структура для перечисления залогиненных пользователей</div><div class="code_line">&nbsp;&nbsp;_WKSTA_USER_INFO_1 = record</div><div class="code_line">&nbsp;&nbsp; &nbsp;wkui1_username: LPWSTR;</div><div class="code_line">&nbsp;&nbsp; &nbsp;wkui1_logon_domain: LPWSTR;</div><div class="code_line">&nbsp;&nbsp; &nbsp;wkui1_oth_domains: LPWSTR;</div><div class="code_line">&nbsp;&nbsp; &nbsp;wkui1_logon_server: LPWSTR;</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;&nbsp;WKSTA_USER_INFO_1 = _WKSTA_USER_INFO_1;</div><div class="code_line">&nbsp;&nbsp;PWKSTA_USER_INFO_1 = ^_WKSTA_USER_INFO_1;</div><div class="code_line">&nbsp;&nbsp;LPWKSTA_USER_INFO_1 = ^_WKSTA_USER_INFO_1;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Структура для определения принадлежности пользователя к группам</div><div class="code_line">&nbsp;&nbsp;PGroupUsersInfo0 = ^_GROUP_USERS_INFO_0;</div><div class="code_line">&nbsp;&nbsp;_GROUP_USERS_INFO_0 = packed record</div><div class="code_line">&nbsp;&nbsp; &nbsp;grui0_name: LPWSTR;</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;&nbsp;TGroupUsersInfo0 = _GROUP_USERS_INFO_0;</div><div class="code_line">&nbsp;&nbsp;GROUP_USERS_INFO_0 = _GROUP_USERS_INFO_0;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Структура для отределения доступных сетевых ресурсов</div><div class="code_line">&nbsp;&nbsp;PSHARE_INFO_1 = ^SHARE_INFO_1;</div><div class="code_line">&nbsp;&nbsp;_SHARE_INFO_1 = record</div><div class="code_line">&nbsp;&nbsp; &nbsp;shi1_netname: LMSTR;</div><div class="code_line">&nbsp;&nbsp; &nbsp;shi1_type: DWORD;</div><div class="code_line">&nbsp;&nbsp; &nbsp;shi1_remark: LMSTR;</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;&nbsp;SHARE_INFO_1 = _SHARE_INFO_1;</div><div class="code_line">&nbsp;&nbsp;TShareInfo1 = SHARE_INFO_1;</div><div class="code_line">&nbsp;&nbsp;PShareInfo1 = PSHARE_INFO_1;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;TMainForm = class(TForm)</div><div class="code_line">&nbsp;&nbsp; &nbsp;gbIP: TGroupBox;</div><div class="code_line">&nbsp;&nbsp; &nbsp;gbInfo: TGroupBox;</div><div class="code_line">&nbsp;&nbsp; &nbsp;memInfo: TMemo;</div><div class="code_line">&nbsp;&nbsp; &nbsp;btnGetInfo: TButton;</div><div class="code_line">&nbsp;&nbsp; &nbsp;procedure btnGetInfoClick(Sender: TObject);</div><div class="code_line">&nbsp;&nbsp; &nbsp;procedure FormCreate(Sender: TObject);</div><div class="code_line">&nbsp;&nbsp;private</div><div class="code_line">&nbsp;&nbsp; &nbsp;IP, Font: Integer; &nbsp;// Это переменные для работы с</div><div class="code_line">&nbsp;&nbsp; &nbsp;edIP: HWND; &nbsp; &nbsp; &nbsp; &nbsp; // WC_IPADDRESS классом</div><div class="code_line">&nbsp;&nbsp; &nbsp;function GetNameFromIP(const IP: String): String;</div><div class="code_line">&nbsp;&nbsp; &nbsp;function GetUsers(const CompName: String): String;</div><div class="code_line">&nbsp;&nbsp; &nbsp;function GetDomain(const CompName, Provider: String): String;</div><div class="code_line">&nbsp;&nbsp; &nbsp;function GetComment(CompName, Provider: String): String;</div><div class="code_line">&nbsp;&nbsp; &nbsp;function GetProvider(const CompName: String): String;</div><div class="code_line">&nbsp;&nbsp; &nbsp;function GetMacFromIP(const IP: String): String;</div><div class="code_line">&nbsp;&nbsp; &nbsp;function GetDomainServer(const DomainName: String): String;</div><div class="code_line">&nbsp;&nbsp; &nbsp;function GetGroups(DomainServer: String; UserName: String): String;</div><div class="code_line">&nbsp;&nbsp; &nbsp;function GetShares(const CompName: String): String;</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Объявим функции, так как их объявлений нет в Дельфи.</div><div class="code_line">&nbsp;&nbsp;// Здесь идет статическая загрузка библиотек, только потому,</div><div class="code_line">&nbsp;&nbsp;// что данные функции есть во всех системах, начиная с W95...</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;{$EXTERNALSYM WNetGetResourceInformation}</div><div class="code_line">&nbsp;&nbsp;function WNetGetResourceInformation(lpNetResource: PNetResource;</div><div class="code_line">&nbsp;&nbsp; &nbsp;lpBuffer: Pointer; var lpcbBuffer: DWORD; lplpSystem: Pointer): DWORD; stdcall;</div><div class="code_line">&nbsp;&nbsp;{$EXTERNALSYM GetIpNetTable}</div><div class="code_line">&nbsp;&nbsp;function GetIpNetTable(pIpNetTable: PTMibIPNetTable;</div><div class="code_line">&nbsp;&nbsp; &nbsp;pdwSize: PULONG; bOrder: Boolean): DWORD; stdcall;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;function WNetGetResourceInformation; external mpr name &#39;WNetGetResourceInformationA&#39;;</div><div class="code_line">&nbsp;&nbsp;function GetIpNetTable; external IPHLPAPI name &#39;GetIpNetTable&#39;;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;function NetGetAnyDCName(servername: LPCWSTR; &nbsp;domainname: LPCWSTR;</div><div class="code_line">&nbsp;&nbsp; &nbsp;bufptr: Pointer): Cardinal;</div><div class="code_line">&nbsp;&nbsp; &nbsp;stdcall; external &#39;netapi32.dll&#39;;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;function NetShareEnum(servername: LMSTR; level: DWORD; var bufptr: Pointer;</div><div class="code_line">&nbsp;&nbsp; &nbsp;prefmaxlen: DWORD; entriesread, totalentries,</div><div class="code_line">&nbsp;&nbsp; &nbsp;resume_handle: LPDWORD): NET_API_STATUS; stdcall; external &#39;Netapi32.dll&#39;;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;function NetApiBufferFree(buffer: Pointer): Cardinal;</div><div class="code_line">&nbsp;&nbsp; &nbsp;stdcall; external &#39;netapi32.dll&#39;;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;function NetWkstaUserEnum(ServerName: LPCWSTR;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Level: DWORD;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;BufPtr: Pointer;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;PrefMaxLen: DWORD;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;EntriesRead: LPDWORD;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;TotalEntries: LPDWORD;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ResumeHandle: LPDWORD): LongInt; stdcall; external &#39;netapi32.dll&#39;;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;function NetUserGetGroups(ServerName: LPCWSTR;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;UserName: LPCWSTR;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;level: DWORD;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;bufptr: Pointer;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;prefmaxlen: DWORD;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;var entriesread: DWORD;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;var totalentries: DWORD): LongInt; stdcall; external &#39;netapi32.dll&#39;;</div><div class="code_line">&nbsp;</div><div class="code_line">var</div><div class="code_line">&nbsp;&nbsp;MainForm: TMainForm;</div><div class="code_line">&nbsp;</div><div class="code_line">implementation</div><div class="code_line">&nbsp;</div><div class="code_line">{$R *.dfm}</div><div class="code_line">&nbsp;</div><div class="code_line">// Для ввода IP адреса будем использовать класс WC_IPADDRESS</div><div class="code_line">// именно для этого и предназначеный...</div><div class="code_line">procedure TMainForm.FormCreate(Sender: TObject);</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp;// Зададим первоначальный IP адрес (это адрес моей машины)</div><div class="code_line">&nbsp;&nbsp;IP := MAKEIPADDRESS(192, 168, 2, 108);</div><div class="code_line">&nbsp;&nbsp;// Инициализируем дополнительные классы библиотеки ComCtl32.dll.</div><div class="code_line">&nbsp;&nbsp;InitCommonControl(ICC_INTERNET_CLASSES);</div><div class="code_line">&nbsp;&nbsp;// Создадим само окошко (предком ему будет gbIP)</div><div class="code_line">&nbsp;&nbsp;edIP:= CreateWindow(WC_IPADDRESS, nil, WS_CHILD or WS_VISIBLE,</div><div class="code_line">&nbsp;&nbsp; &nbsp;6, 16, 100, 21, gbIP.Handle, 0, hInstance, nil);</div><div class="code_line">&nbsp;&nbsp;// Укажем ему какой IP показывать</div><div class="code_line">&nbsp;&nbsp;SendMessage(edIP, IPM_SETADDRESS, 0, IP);</div><div class="code_line">&nbsp;&nbsp;// Подберем нужный шрифтик для него...</div><div class="code_line">&nbsp;&nbsp;Font := CreateFont(-11, 0, 0, 0, 400, 0, 0, 0, DEFAULT_CHARSET,</div><div class="code_line">&nbsp;&nbsp; &nbsp;OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,</div><div class="code_line">&nbsp;&nbsp; &nbsp;DEFAULT_PITCH or FF_DONTCARE, &#39;MS Sans Serif&#39;);</div><div class="code_line">&nbsp;&nbsp;// и скажем, чтоб он был с этим шрифтом (а то больно уж неказистый...)</div><div class="code_line">&nbsp;&nbsp;SendMessage(edIP, WM_SETFONT, Font, 0);</div><div class="code_line">end;</div><div class="code_line">&nbsp;</div><div class="code_line">// Ну это короче понятно...</div><div class="code_line">procedure TMainForm.btnGetInfoClick(Sender: TObject);</div><div class="code_line">var</div><div class="code_line">&nbsp;&nbsp;TmpCompName, TmpProvider, TmpGroup, TmpUser, TmpServer: String;</div><div class="code_line">&nbsp;&nbsp;Time: Cardinal;</div><div class="code_line">&nbsp;&nbsp;IPStr: String;</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp;Time := GetTickCount; &nbsp;// Засечем время...</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Узнаем, что за адрес введен... (он появится в IP)</div><div class="code_line">&nbsp;&nbsp;SendMessage(edIP, IPM_GETADDRESS, 0, Longint(PDWORD(@IP)));</div><div class="code_line">&nbsp;&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Преобразуем эту абракадабру в нормальный &quot;Dotted IP&quot;</div><div class="code_line">&nbsp;&nbsp;IPStr := IntToStr(FIRST_IPADDRESS(IP));</div><div class="code_line">&nbsp;&nbsp;IPStr := IPStr + &#39;.&#39; + IntToStr(SECOND_IPADDRESS(IP));</div><div class="code_line">&nbsp;&nbsp;IPStr := IPStr + &#39;.&#39; + IntToStr(THIRD_IPADDRESS(IP));</div><div class="code_line">&nbsp;&nbsp;IPStr := IPStr + &#39;.&#39; + IntToStr(FOURTH_IPADDRESS(IP));</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Ну и начнем работать...</div><div class="code_line">&nbsp;&nbsp;with memInfo, memInfo.Lines do &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Вывод информации</div><div class="code_line">&nbsp;&nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp;Clear; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Очищаем экран</div><div class="code_line">&nbsp;&nbsp; &nbsp;Refresh; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Ну и обновляем...</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// (при вызове первой функции может не обновиться)</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;Add(RES_IP + IPStr); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Выводим IP адрес</div><div class="code_line">&nbsp;&nbsp; &nbsp;TmpCompName := GetNameFromIP(IPStr);</div><div class="code_line">&nbsp;&nbsp; &nbsp;if TmpCompName = RES_UNKNOWN then Exit;</div><div class="code_line">&nbsp;&nbsp; &nbsp;Add(RES_CMP + TmpCompName); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Выводим имя компьютера</div><div class="code_line">&nbsp;&nbsp; &nbsp;TmpUser := GetUsers(IPStr);</div><div class="code_line">&nbsp;&nbsp; &nbsp;Add(RES_USR + TmpUser); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Выводим имя пользователя</div><div class="code_line">&nbsp;&nbsp; &nbsp;TmpProvider := GetProvider(TmpCompName);</div><div class="code_line">&nbsp;&nbsp; &nbsp;Add(RES_PROV + TmpProvider); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Выводим провайдера</div><div class="code_line">&nbsp;&nbsp; &nbsp;Add(RES_COM + GetComment(TmpCompName,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;TmpProvider)); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Выводим комментарий к ресурсу</div><div class="code_line">&nbsp;&nbsp; &nbsp;TmpGroup := GetDomain(TmpCompName, TmpProvider);</div><div class="code_line">&nbsp;&nbsp; &nbsp;Add(RES_DOM + TmpGroup); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Выводим группу</div><div class="code_line">&nbsp;&nbsp; &nbsp;TmpServer := GetDomainServer(TmpGroup);</div><div class="code_line">&nbsp;&nbsp; &nbsp;if TmpServer &#60;&#62; &#39;&#39; then</div><div class="code_line">&nbsp;&nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Add(RES_SER + TmpServer); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Выводим имя сервера</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Add(RES_GRP + GetGroups(TmpServer, TmpUser)); &nbsp; &nbsp; // Выводим группы домена в которые входит пользователь</div><div class="code_line">&nbsp;&nbsp; &nbsp;end;</div><div class="code_line">&nbsp;&nbsp; &nbsp;Add(RES_SHARES + GetShares(TmpCompName)); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Выводим список доступных ресурсов</div><div class="code_line">&nbsp;&nbsp; &nbsp;Add(RES_MAC + GetMacFromIP(IPStr)); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Выводим МАС адрес</div><div class="code_line">&nbsp;&nbsp; &nbsp;Add(RES_TIME + IntToStr(GetTickCount - Time)); &nbsp; &nbsp; &nbsp;// Сколько времени затрачено</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">end;</div><div class="code_line">&nbsp;</div><div class="code_line">// Вообщето желательно запускать данную функцию отдельным потоком.</div><div class="code_line">// Поясню: при отсутствии компьютера с заданным IP программа будет</div><div class="code_line">// ожидать выполнения gethostbyaddr и на это время подвиснет.</div><div class="code_line">function TMainForm.GetNameFromIP(const IP: String): String;</div><div class="code_line">var</div><div class="code_line">&nbsp;&nbsp;WSA: TWSAData;</div><div class="code_line">&nbsp;&nbsp;Host: PHostEnt;</div><div class="code_line">&nbsp;&nbsp;Addr: Integer;</div><div class="code_line">&nbsp;&nbsp;Err: Integer;</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp;Result := RES_UNKNOWN;</div><div class="code_line">&nbsp;&nbsp;Err := WSAStartup(WSA_TYPE, WSA);</div><div class="code_line">&nbsp;&nbsp;if Err &#60;&#62; 0 then &nbsp;// Лучше пользоваться такой конструкцией,</div><div class="code_line">&nbsp;&nbsp;begin &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // чтобы в случае ошибки можно было увидеть ее код.</div><div class="code_line">&nbsp;&nbsp; &nbsp;ShowMessage(SysErrorMessage(GetLastError));</div><div class="code_line">&nbsp;&nbsp; &nbsp;Exit;</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;&nbsp;try</div><div class="code_line">&nbsp;&nbsp; &nbsp;Addr := inet_addr(PChar(IP));</div><div class="code_line">&nbsp;&nbsp; &nbsp;if Addr = INADDR_NONE then</div><div class="code_line">&nbsp;&nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;ShowMessage(SysErrorMessage(GetLastError));</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;WSACleanup;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Exit;</div><div class="code_line">&nbsp;&nbsp; &nbsp;end;</div><div class="code_line">&nbsp;&nbsp; &nbsp;Host := gethostbyaddr(@Addr, SizeOf(Addr), PF_INET);</div><div class="code_line">&nbsp;&nbsp; &nbsp;if Assigned(Host) then &nbsp;// Обязательная проверка, в противном случае, при</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Result := Host.h_name // отсутствии компьютера с заданым IP, получим AV</div><div class="code_line">&nbsp;&nbsp; &nbsp;else</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;ShowMessage(SysErrorMessage(GetLastError));</div><div class="code_line">&nbsp;&nbsp;finally</div><div class="code_line">&nbsp;&nbsp; &nbsp;WSACleanup;</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">end;</div><div class="code_line">&nbsp;</div><div class="code_line">// Перечисляем всех залогиненных на машине пользователей</div><div class="code_line">// начинаем перечисления со второго пользователя, потомчто</div><div class="code_line">// первым будет &quot;имя компьютера&quot;$</div><div class="code_line">function TMainForm.GetUsers(const CompName: String): String;</div><div class="code_line">var</div><div class="code_line">&nbsp;&nbsp;Buffer, tmpBuffer: Pointer;</div><div class="code_line">&nbsp;&nbsp;PrefMaxLen &nbsp; &nbsp; &nbsp; : DWORD;</div><div class="code_line">&nbsp;&nbsp;Resume_Handle &nbsp; &nbsp;: DWORD;</div><div class="code_line">&nbsp;&nbsp;EntriesRead &nbsp; &nbsp; &nbsp;: DWORD;</div><div class="code_line">&nbsp;&nbsp;TotalEntries &nbsp; &nbsp; : DWORD;</div><div class="code_line">&nbsp;&nbsp;I, Size &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: Integer;</div><div class="code_line">&nbsp;&nbsp;PSrvr &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;: PWideChar;</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp;PSrvr := nil;</div><div class="code_line">&nbsp;&nbsp;try</div><div class="code_line">&nbsp;&nbsp; &nbsp;// Переводим имя компьютера типа PWideChar</div><div class="code_line">&nbsp;&nbsp; &nbsp;Size := Length(CompName);</div><div class="code_line">&nbsp;&nbsp; &nbsp;GetMem(PSrvr, Size * SizeOf(WideChar) + 1);</div><div class="code_line">&nbsp;&nbsp; &nbsp;StringToWideChar(CompName, PSrvr, Size + 1);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;PrefMaxLen := DWORD(-1);</div><div class="code_line">&nbsp;&nbsp; &nbsp;EntriesRead := 0;</div><div class="code_line">&nbsp;&nbsp; &nbsp;TotalEntries := 0;</div><div class="code_line">&nbsp;&nbsp; &nbsp;Resume_Handle := 0;</div><div class="code_line">&nbsp;&nbsp; &nbsp;Buffer := nil;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;// Получаем список пользователей на компьютере из PSrvr</div><div class="code_line">&nbsp;&nbsp; &nbsp;if NetWkstaUserEnum( PSrvr, 1, @Buffer, PrefMaxLen, @EntriesRead,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;@TotalEntries, @Resume_Handle) = S_OK then</div><div class="code_line">&nbsp;&nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;tmpBuffer := Pointer(DWORD(Buffer) + SizeOf(WKSTA_USER_INFO_1));</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;for I := 1 to TotalEntries - 1 do</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Result := Result + WKSTA_USER_INFO_1(tmpBuffer^).wkui1_username + &#39;, &#39;;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;tmpBuffer := Pointer(DWORD(tmpBuffer) + SizeOf(WKSTA_USER_INFO_1));</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;end;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Result := Copy(Result, 1, Length(Result) - 2);</div><div class="code_line">&nbsp;&nbsp;end</div><div class="code_line">&nbsp;&nbsp;else</div><div class="code_line">&nbsp;&nbsp; &nbsp;ShowMessage(SysErrorMessage(GetLastError));</div><div class="code_line">&nbsp;&nbsp;finally</div><div class="code_line">&nbsp;&nbsp; &nbsp;NetApiBufferFree(Buffer);</div><div class="code_line">&nbsp;&nbsp; &nbsp;FreeMem(PSrvr);</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">end;</div><div class="code_line">&nbsp;</div><div class="code_line">// Все-таки будем сканировать сеть, НО!!!</div><div class="code_line">// Мы не будем производить рекурсивное сканирование ресурсов с</div><div class="code_line">// dwDisplayType равным RESOURCEDISPLAYTYPE_SERVER!!!</div><div class="code_line">// В основном все торможение происходить именно здесь,</div><div class="code_line">// так как эти ресурсы являются так называемыми корневыми</div><div class="code_line">// для компьютеров. Если компьютер отключен его имя может сохраниться</div><div class="code_line">// в кэше и при попытке сканирования получим ненужные нам тормоза.</div><div class="code_line">// В принципе, у меня эта функция выдавала неплохие результаты по скорости...</div><div class="code_line">// (Около 31 мс - максимум с отображением на memInfo, сеть 100Мб, 28 компов)</div><div class="code_line">&nbsp;</div><div class="code_line">function TMainForm.GetComment(CompName, Provider: String): String;</div><div class="code_line">var</div><div class="code_line">&nbsp;&nbsp;StopScan: Boolean;</div><div class="code_line">&nbsp;&nbsp;TmpRes: TNetResource;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Само сканирование</div><div class="code_line">&nbsp;&nbsp;procedure Scan(Res: TNetResource; Root: boolean);</div><div class="code_line">&nbsp;&nbsp;var</div><div class="code_line">&nbsp;&nbsp; &nbsp;Enum, I: Cardinal;</div><div class="code_line">&nbsp;&nbsp; &nbsp;ScanRes: array [0..512] of TNetResource; // Можно сделать и больший размер массива</div><div class="code_line">&nbsp;&nbsp; &nbsp;Size, Entries, Err: DWORD; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // но, как показывает практика, такого достаточно</div><div class="code_line">&nbsp;&nbsp;begin</div><div class="code_line">&nbsp;&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;if StopScan then Exit; // Используем флаг для выхода из рекурсии</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;// Ну тут думаю все понятно... просто два типа начала сканирования</div><div class="code_line">&nbsp;&nbsp; &nbsp;if Root = True then</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Err := WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;0, nil, Enum) // корневой...</div><div class="code_line">&nbsp;&nbsp; &nbsp;else</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Err := WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_DISK,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;0, @Res, Enum); // и рекурсионный для поиска вложений...</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;if Err = NO_ERROR then</div><div class="code_line">&nbsp;&nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Size := SizeOf(ScanRes);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Entries := DWORD(-1);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Err := WNetEnumResource(Enum, Entries, @ScanRes, Size);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;if Err = NO_ERROR then</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;try</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;for I := 0 to Entries - 1 do</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if StopScan then Exit; // Еще один флаг, так как выход на верхний вызов</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;with ScanRes[i] do &nbsp; &nbsp; // может осуществиться из цикла</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if dwDisplayType = RESOURCEDISPLAYTYPE_SERVER then</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if lpRemoteName = CompName then // если нашли наш компьютер...</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Result := &nbsp;lpComment; &nbsp; &nbsp; // вытаскиваем комментарий</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;StopScan := True; &nbsp; &nbsp; &nbsp; &nbsp; // и выставляем флаг для выхода из рекуссии</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Exit;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;end;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if dwDisplayType &#60;&#62; RESOURCEDISPLAYTYPE_SERVER then &nbsp;// не будем сканировать шары у компов...</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Scan(ScanRes[i], False);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;end;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;end;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;finally</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;WNetCloseEnum(Enum);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;end</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;else</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;if Err &#60;&#62; ERROR_NO_MORE_ITEMS then &nbsp;// Нет элементов для отображения...</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;MessageDlg(SysErrorMessage(GetLastError), mtError, [mbOK], 0);</div><div class="code_line">&nbsp;&nbsp; &nbsp;end</div><div class="code_line">&nbsp;&nbsp; &nbsp;else</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;ShowMessage(SysErrorMessage(GetLastError));</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;</div><div class="code_line">// Основная процедура</div><div class="code_line">begin</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Подготовительные действия...</div><div class="code_line">&nbsp;&nbsp;Result := RES_UNKNOWN;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;if CompName = RES_UNKNOWN then Exit; &nbsp; &nbsp;// Если имя компа не найдено,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// незачем и продолжать.</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;CompName := &#39;\&#39; + CompName; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Подправим имя,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// чтоб не делать это далее в цикле...</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;StopScan := False; &nbsp; &nbsp;// Снимем флаг выхода из рекурсии.</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Здесь обязательно инициализирование переменной</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// типа Boolean, так как было замечено, что</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// некоторые версии Дельфи криво инициализируют</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// значение по умолчанию, после чего логические</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// операторы типа AND - OR - NOT перестают работать.</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Например: по умолчанию переменная StopScan равна False</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// без инициализации, после StopScan := not StopScan;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// переменная StopScan НЕ ВСЕГДА станет True!!!</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Запускаем сканирование...</div><div class="code_line">&nbsp;&nbsp;// (можно и в потоке, но у меня время на сканирование уходит 8 мс.)</div><div class="code_line">&nbsp;&nbsp;Scan(TmpRes, True);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// И смотрим результаты...</div><div class="code_line">&nbsp;&nbsp;if Result = &#39;&#39; then Result := RES_COM_NO;</div><div class="code_line">end;</div><div class="code_line">&nbsp;</div><div class="code_line">// Задача этой функции предельно проста:</div><div class="code_line">// При известном имени компьютера мы можем заполнить структуру</div><div class="code_line">// и передать ее функции WNetGetResourceParent которая и вернет</div><div class="code_line">// нам предка, в моем случае группу.</div><div class="code_line">// Да, чуть не забыл, если имя компьютера есть в кэше, а сам</div><div class="code_line">// компьютер отключен, то в качестве результата будет либо</div><div class="code_line">// пустая строка либо &#39;Нет данных&#39;...</div><div class="code_line">// Поэтому опять придется сканировать, если слишком уж критично...</div><div class="code_line">function TMainForm.GetDomain(const CompName, Provider: String): String;</div><div class="code_line">var</div><div class="code_line">&nbsp;&nbsp;CurrRes: TNetResource;</div><div class="code_line">&nbsp;&nbsp;ParentName: array [0..1] of TNetResource;</div><div class="code_line">&nbsp;&nbsp;Enum: DWORD;</div><div class="code_line">&nbsp;&nbsp;Err: Integer;</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp;with CurrRes do</div><div class="code_line">&nbsp;&nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp;dwScope := RESOURCE_GLOBALNET;</div><div class="code_line">&nbsp;&nbsp; &nbsp;dwType := RESOURCETYPE_DISK;</div><div class="code_line">&nbsp;&nbsp; &nbsp;dwDisplayType := RESOURCEDISPLAYTYPE_SERVER;</div><div class="code_line">&nbsp;&nbsp; &nbsp;dwUsage := RESOURCEUSAGE_CONTAINER;</div><div class="code_line">&nbsp;&nbsp; &nbsp;lpLocalName := &#39;&#39;;</div><div class="code_line">&nbsp;&nbsp; &nbsp;lpRemoteName := PChar(&#39;\&#39; + CompName);</div><div class="code_line">&nbsp;&nbsp; &nbsp;lpComment := &#39;&#39;;</div><div class="code_line">&nbsp;&nbsp; &nbsp;lpProvider := PChar(Provider);</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;&nbsp;Enum := SizeOf(ParentName);</div><div class="code_line">&nbsp;&nbsp;Err := WNetGetResourceParent(@CurrRes, @ParentName, Enum);</div><div class="code_line">&nbsp;&nbsp;if Err = NO_ERROR then</div><div class="code_line">&nbsp;&nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp;Result := ParentName[0].lpRemoteName;</div><div class="code_line">&nbsp;&nbsp; &nbsp;if Result = &#39;&#39; then Result := RES_COM_NO;</div><div class="code_line">&nbsp;&nbsp;end</div><div class="code_line">&nbsp;&nbsp;else</div><div class="code_line">&nbsp;&nbsp; &nbsp;ShowMessage(SysErrorMessage(GetLastError));</div><div class="code_line">end;</div><div class="code_line">&nbsp;</div><div class="code_line">// А этой функцией мы можем узнать провайдера</div><div class="code_line">// (в основном это Microsoft Network).</div><div class="code_line">function TMainForm.GetProvider(const CompName: String): String;</div><div class="code_line">var</div><div class="code_line">&nbsp;&nbsp;Buffer: array [0..255] of Char;</div><div class="code_line">&nbsp;&nbsp;Size: DWORD;</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp;Size := SizeOf(Buffer);</div><div class="code_line">&nbsp;&nbsp;if WNetGetProviderName(WNNC_NET_LANMAN, @Buffer, Size) &#60;&#62; NO_ERROR then</div><div class="code_line">&nbsp;&nbsp; &nbsp;Result := RES_COM_NO</div><div class="code_line">&nbsp;&nbsp;else</div><div class="code_line">&nbsp;&nbsp; &nbsp;Result := String(Buffer);</div><div class="code_line">end;</div><div class="code_line">&nbsp;</div><div class="code_line">// Из всех приведенных функций эта самая интересная.</div><div class="code_line">// Я много раз говорил о незаслуженном невнимании программистов</div><div class="code_line">// к IPHLPAPI.DLL. Данный пример подтверждает это. На всех форумах</div><div class="code_line">// можно услышать о получании МАС адреса посредством посылки IPX пакета</div><div class="code_line">// и разбора заголовка ответа от удаленного компьютера</div><div class="code_line">// (что само по себе геморой, если не принимать во внимание,</div><div class="code_line">// что IPX уже практически вымер, и его мало где встретишь).</div><div class="code_line">// Здесь же строится полная ARP таблица, на основании которой мы</div><div class="code_line">// можем спокойно произвести выборку по нужному IP адресу,</div><div class="code_line">// а так как все берется из кэша, то мы сможем узнать МАС адреса</div><div class="code_line">// даже выключенных компьютеров... </div><div class="code_line">// Единственный минус: в таблице (не всегда) отсутсвует информация</div><div class="code_line">// по локальному компьютеру, т.е. таким образом можно получить</div><div class="code_line">// все МАС адреса за исключением своего,</div><div class="code_line">// но для этого есть уже другие функции...</div><div class="code_line">&nbsp;</div><div class="code_line">// Приведу выдержку из MSDN:</div><div class="code_line">// You can use IP Helper to perform Address Resolution Protocol (ARP) operations for the local computer. </div><div class="code_line">// Use the following functions to retrieve and modify the ARP table.</div><div class="code_line">// The GetIpNetTable retrieves the ARP table. </div><div class="code_line">// The ARP table contains the mapping of IP addresses to physical addresses. </div><div class="code_line">// Physical addresses are sometimes referred to as Media Access Controller (MAC) addresses. </div><div class="code_line">&nbsp;</div><div class="code_line">// Хочу заметить что для NT есть очень интересная функция SendARP - позволяющая</div><div class="code_line">// напрямую получить требуемый МАС без построения таблицы, поэтому советую</div><div class="code_line">// модифицировать код программы для более эффективного исполнения участков кода </div><div class="code_line">// под различными системами.</div><div class="code_line">&nbsp;</div><div class="code_line">function TMainForm.GetMacFromIP(const IP: String): String;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// (Будем использовать функцию приведения из статьи)</div><div class="code_line">&nbsp;&nbsp;// В качестве первого значения массив, второе значение,</div><div class="code_line">&nbsp;&nbsp;// размер данных в массиве</div><div class="code_line">&nbsp;&nbsp;function GetMAC(Value: TMacAddress; Length: DWORD): String;</div><div class="code_line">&nbsp;&nbsp;var</div><div class="code_line">&nbsp;&nbsp; &nbsp;I: Integer;</div><div class="code_line">&nbsp;&nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp;if Length = 0 then Result := &#39;00-00-00-00-00-00&#39; else</div><div class="code_line">&nbsp;&nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Result := &#39;&#39;;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;for i:= 0 to Length -2 do</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Result := Result + IntToHex(Value[i], 2) + &#39;-&#39;;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Result := Result + IntToHex(Value[Length-1], 2);</div><div class="code_line">&nbsp;&nbsp; &nbsp;end;</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Получаем IP адрес, заметь в отличии от работы с классом WC_IPADDRESS</div><div class="code_line">&nbsp;&nbsp;// здесь преобразование идет в обратном порядке!</div><div class="code_line">&nbsp;&nbsp;function GetDottedIPFromInAddr(const InAddr: Integer): String;</div><div class="code_line">&nbsp;&nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp;Result := &#39;&#39;;</div><div class="code_line">&nbsp;&nbsp; &nbsp;Result := IntToStr(FOURTH_IPADDRESS(InAddr));</div><div class="code_line">&nbsp;&nbsp; &nbsp;Result := Result + &#39;.&#39; + IntToStr(THIRD_IPADDRESS(InAddr));</div><div class="code_line">&nbsp;&nbsp; &nbsp;Result := Result + &#39;.&#39; + IntToStr(SECOND_IPADDRESS(InAddr));</div><div class="code_line">&nbsp;&nbsp; &nbsp;Result := Result + &#39;.&#39; + IntToStr(FIRST_IPADDRESS(InAddr));</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp;// Основная функция</div><div class="code_line">var</div><div class="code_line">&nbsp;&nbsp;Table: TMibIPNetTable;</div><div class="code_line">&nbsp;&nbsp;Size: Integer;</div><div class="code_line">&nbsp;&nbsp;CatchIP: String;</div><div class="code_line">&nbsp;&nbsp;Err, I: Integer;</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp;Result := RES_UNKNOWN;</div><div class="code_line">&nbsp;&nbsp;Size := SizeOf(Table); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// Ну тут все просто...</div><div class="code_line">&nbsp;&nbsp;Err := GetIpNetTable(@Table, @Size, False); // Выполняем...</div><div class="code_line">&nbsp;&nbsp;if Err &#60;&#62; NO_ERROR then &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Проверка на ошибку...</div><div class="code_line">&nbsp;&nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp;ShowMessage(SysErrorMessage(GetLastError));</div><div class="code_line">&nbsp;&nbsp; &nbsp;Exit;</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">&nbsp;&nbsp;// Теперь мы имеем таблицу из IP адресов и соответсвующих им MAC адресов</div><div class="code_line">&nbsp;&nbsp;for I := 0 to Table.dwNumEntries - 1 do &nbsp; &nbsp; // Ищем нужный IP ...</div><div class="code_line">&nbsp;&nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp;CatchIP := GetDottedIPFromInAddr(Table.Table[I].dwAddr);</div><div class="code_line">&nbsp;&nbsp; &nbsp;if CatchIP = IP then &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// И выводим его МАС ...</div><div class="code_line">&nbsp;&nbsp; &nbsp;begin</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Result := GetMAC(Table.Table[I].bPhysAddr, Table.Table[I].dwPhysAddrLen);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Break;</div><div class="code_line">&nbsp;&nbsp; &nbsp;end;</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">end;</div><div class="code_line">&nbsp;</div><div class="code_line">// Полуение доступных сетевых ресурсов на удаленном компьютере</div><div class="code_line">function TMainForm.GetShares(const CompName: String): String;</div><div class="code_line">type TShareInfo1Array = array of TShareInfo1;</div><div class="code_line">var</div><div class="code_line">&nbsp;&nbsp;entriesread, totalentries: DWORD;</div><div class="code_line">&nbsp;&nbsp;Info: Pointer;</div><div class="code_line">&nbsp;&nbsp;I: Integer;</div><div class="code_line">&nbsp;&nbsp;CN: PWideChar;</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp;CN := StringToOleStr(CompName);</div><div class="code_line">&nbsp;&nbsp;// так как нам нужны только имена ресурсов, воспользуемся струтурой TShareInfo1</div><div class="code_line">&nbsp;&nbsp;// тогда, не нужно будет получать привилегии администратора на удаленной машине :)</div><div class="code_line">&nbsp;&nbsp;if NetShareEnum(CN, 1, Info, DWORD(-1), @entriesread,</div><div class="code_line">&nbsp;&nbsp; &nbsp;@totalentries, nil) = 0 then</div><div class="code_line">&nbsp;&nbsp; &nbsp;try // список ресурсов смотрим здесь</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;if entriesread &#62; 0 then</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;for I := 0 to entriesread - 1 do</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Result := Result + TShareInfo1Array(@(Info^))[I].shi1_netname + &#39; &#39;;</div><div class="code_line">&nbsp;&nbsp; &nbsp;finally</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;NetApiBufferFree(Info);</div><div class="code_line">&nbsp;&nbsp; &nbsp;end;</div><div class="code_line">end;</div><div class="code_line">&nbsp;</div><div class="code_line">// Вот таким простым путем будем получать имя сервера домена</div><div class="code_line">function TMainForm.GetDomainServer(const DomainName: String): String;</div><div class="code_line">var</div><div class="code_line">&nbsp;&nbsp;Domain, Server: PWideChar;</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp;GetMem(Domain, MAX_PATH);</div><div class="code_line">&nbsp;&nbsp;try</div><div class="code_line">&nbsp;&nbsp; &nbsp;StringToWideChar(DomainName, Domain, MAX_PATH);</div><div class="code_line">&nbsp;&nbsp; &nbsp;if NetGetAnyDCName(nil, Domain, @Server)= NO_ERROR then</div><div class="code_line">&nbsp;&nbsp; &nbsp;try</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;Result := WideCharToString(Server);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;finally</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;NetApiBufferFree(Server);</div><div class="code_line">&nbsp;&nbsp; &nbsp;end;</div><div class="code_line">&nbsp;&nbsp;finally</div><div class="code_line">&nbsp;&nbsp; &nbsp;FreeMem(Domain, MAX_PATH);</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">end;</div><div class="code_line">&nbsp;</div><div class="code_line">// перечисление доменных групп в которые входит пользователь</div><div class="code_line">function TMainForm.GetGroups(DomainServer: String; UserName: String): String;</div><div class="code_line">type</div><div class="code_line">&nbsp;&nbsp;TGroupUsersInfoArray = array of TGroupUsersInfo0;</div><div class="code_line">var</div><div class="code_line">&nbsp;&nbsp;Info: PGroupUsersInfo0;</div><div class="code_line">&nbsp;&nbsp;Sn, Un: PWideChar;</div><div class="code_line">&nbsp;&nbsp;entriesread, totalentries: DWORD;</div><div class="code_line">&nbsp;&nbsp;I, A, B, Size: Integer;</div><div class="code_line">&nbsp;&nbsp;P: Pointer;</div><div class="code_line">begin</div><div class="code_line">&nbsp;&nbsp;// нам нужно только имя сервера домена</div><div class="code_line">&nbsp;&nbsp;Sn := StringToOLEStr(DomainServer);</div><div class="code_line">&nbsp;&nbsp;// и имя пользователя</div><div class="code_line">&nbsp;&nbsp;Un := StringToOleStr(UserName);</div><div class="code_line">&nbsp;&nbsp;// делаем запрос</div><div class="code_line">&nbsp;&nbsp;if NetUserGetGroups(Sn, Un, 0, @Info, DWORD(-1), entriesread, totalentries) = NO_ERROR &nbsp;then</div><div class="code_line">&nbsp;&nbsp;try // и смотрим, что там у нас получилось</div><div class="code_line">&nbsp;&nbsp; &nbsp;if entriesread &#62; 0 then</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp;for I := 0 to entriesread - 1 do</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Result := Result + TGroupUsersInfoArray(@(Info^))[I].grui0_name + &#39; &#39;;</div><div class="code_line">&nbsp;&nbsp;finally</div><div class="code_line">&nbsp;&nbsp; &nbsp;NetApiBufferFree(Info);</div><div class="code_line">&nbsp;&nbsp;end;</div><div class="code_line">end;</div><div class="code_line">&nbsp;</div><div class="code_line">end.</div></ol></div></div></div></div><script>preloadCodeButtons('1');</script><br>
<br>
Проект также доступен по адресу: http://rouse.front.ru/infofromip.zip]]></description>
        <author>Rouse_</author>
        <category>Интернет, сети, протоколы</category>
      </item>
	
      </channel>
      </rss>
	