Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Проблемы с вызовом XcvDataW [D7, Win2k, WinXP]


alexm_hs ©   (2007-02-04 23:26:00) 

Задача: Получить IP адрес (или имя) сетевого принтера.
Известно: имя хоста, на котором прописан порт принтера

Пытаюсь получить информацию об этом порте через вызов функции XcvData.  Код ошибки - 6 (неверный дескриптор)

как делаю:

.....
var
 XcvData: function(
   hPrinter: THandle;
   pszDataName : PWideChar;
   pInputData : Pointer;
   cbInputData : DWORD;
   pOutputData : Pointer;
   cbOutputData : DWORD;
   var pcbOutputNeeded, pdwStatus: DWORD): BOOL; stdcall;
.....
var hPrinter: thandle;
....
hPrinter := 0;
OpenPrinter('\\HOME', hPrinter, nil);
GetPrinterIP(hPrinter); //хенд ненулевой;

....
function GetPrinterIP(HPrn: THandle): string;
var
 FLibHandle: THandle;
 Buffer: PChar;
 Flags, Count, NumInfo: DWORD;
 s : WideString;
 e: DWORD;

begin
 FLibHandle := LoadLibrary('winspool.drv');
 if FLibHandle = 0 then Exit;
 @XcvData := GetProcAddress(FLibHandle, 'XcvDataW');
 if not Assigned(XcvData) then
 begin
   FreeLibrary(FLibHandle);
   Exit;
 end;

 s := 'L"IPAddress"';

 XcvData(HPrn, PWideChar(s), nil, 0, nil, 0, Count,NumInfo);
  e := GetLastError;

 if Count = 0 then Exit;
 GetMem(Buffer, Count);
 try
   if not XcvData(HPrn, PWideChar(s), nil, 0, PByte(Buffer), Count, Count,NumInfo) then
     Exit;
 finally
   FreeMem(Buffer, Count);
 end;
 FreeLibrary(FLibHandle);
end;

В чем может быть проблема?


alexm_hs   (2007-02-05 19:52:00) [1]

Сам спросил, сам отвечаю :)) РазобралсЯ таки

var
 XcvData: function(
   hPrinter: THandle;
   pszDataName: PWideChar;
   pInputData: Pointer;
   cbInputData: DWORD;
   pOutputData: Pointer;
   cbOutputData: DWORD;
   pcbOutputNeeded, pdwStatus: LPDWORD): BOOL; stdcall;

........................
.....................

function GetPrinterIP(HPrn: THandle): string;
var
 FLibHandle: THandle;
 Buffer: PChar;
 Count, NumInfo: DWORD;
 ip: string;
 i: integer;
 sizebuf: integer;
begin
 result := '';
 FLibHandle := LoadLibrary('winspool.drv');  //подгружаем драйвер спулера
 if FLibHandle = 0 then Exit;
 @XcvData := GetProcAddress(FLibHandle, 'XcvDataW'); //функция не описана в WinSpool - грузим сами
 if not Assigned(XcvData) then
 begin
   FreeLibrary(FLibHandle);
   Exit;
 end;

 XcvData(HPrn, 'IPAddress', nil, 0, nil, 0, @Count, @NumInfo); //вся фишка XcvData - во втором параметре. Описание
 //есть в MSDN, раздел TCPMON Xcv Commands. Один нюанс - если в МСДН описан параметр к примеру L"HostAddress", то
 //В Delphi он же должен выглядеть как 'HostAddress'. Все остальное там понятно.
 if Count = 0 then Exit;
 GetMem(Buffer, Count);
 sizebuf := Count;
 try
   if not XcvData(HPrn, 'IPAddress', nil, 0, PByte(Buffer), Count, @Count, @NumInfo) then
     Exit;
   for i := 0 to sizebuf - 1 do
     if Buffer[i] <> #0 then
       ip := ip + Buffer[i];
   result := ip;
 finally
   FreeMem(Buffer, sizebuf);
 end;
 FreeLibrary(FLibHandle);
end;

///////////////////////////////////////////////////////////////////////////////////////////

function GetPrintersIP: TStrings;
var
 Buffer, PrinterInfo: PChar;
 Count, NumInfo: DWORD;
 I: Integer;
 Level: Byte;
 FPrinters: TStringList;
 hPrinter: THandle;
 pcname, prnname: string;
 prnip: string;
begin
 pcname := '\\server';   ///имя хоста, на котором пропиан порт сетевого принтера
 prnname := '\\server\LJ5K'; //имя сервера печати (имя принтера). Можно получить с помощью WinSpool.EnumPrinters.
 FPrinters := TStringList.Create;
 Result := FPrinters;
 try
   Level := 2;
   Count := 0;

   EnumPorts(PAnsiChar(pcname), level, nil, 0, Count, NumInfo);
   if Count = 0 then Exit;
   GetMem(Buffer, Count);
   try
     if not EnumPorts(PAnsiChar(pcname), Level, PByte(Buffer), Count, Count, NumInfo) then
       Exit;
     PrinterInfo := Buffer;
     for I := 0 to NumInfo - 1 do begin
       if pos('TCP/IP', PPortInfo2A(PrinterInfo)^.pDescription) <> 0 then begin //интересуют только порты TCP/IP
         OpenPrinter(PAnsiChar(prnname + ',XcvPort ' + PPortInfo2A(PrinterInfo)^.pPortName), hPrinter, nil); //первый параметр
         //должен быть строкой типа '\\servername\printername,XcvPort PortName',
         //например: '\\MAINSERV\LJ5K,XcvPort IP_192.168.160.1'
         if hPrinter <> 0 then begin
           prnip := GetPrinterIP(hPrinter);
           FPrinters.Add(prnip);
         end;
         ClosePrinter(hPrinter);
       end;
       Inc(PrinterInfo, sizeof(TPortInfo2A));
     end;
   finally
     FreeMem(Buffer, Count);
   end;
 except
   FPrinters.Free;
   raise;
 end;
 Result := FPrinters;
end;
/////////////////////////////////////////////////////////
procedure TMainLSFrm.ToolButton2Click(Sender: TObject);
var sl: TStringList;
begin
 sl := TStringList.Create;
 sL.Assign(GetPrintersIP);
 //.....///
 SL.Free;
end;


Наверх

Титульная страница Поиск, карта сайта Написать письмо