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

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

SNMP и Delphi 2009 - непонятки с указателем [WinXP]


tytus ©   (2009-08-13 12:07:00) 

Добрый день мастера.
Есть файл Snmp_Api, в нем записи:

 PAsnOctetString = ^TAsnOctetString;
 TAsnOctetString = record
   stream: PByte;
   length: UINT;
   dynam: BOOL;
  end;

 PAsnAny = ^TAsnAny;
 TAsnAny = record
   asnType: BYTE;
    caseInteger of     0: (number: TAsnInteger32);          { ASN_INTEGER, ASN_INTEGER32 }
     1: (unsigned32: TAsnUnsigned32);     { ASN_UNSIGNED32 }
     2: (counter64: TAsnCounter64);       { ASN_COUNTER64 }
     3: (str: TAsnOctetString);           { ASN_OCTETSTRING }
     4: (bits: TAsnBits);                 { ASN_BITS }
     5: (obj: TAsnObjectIdentifier);      { ASN_OBJECTIDENTIFIER }
     6: (sequence: TAsnSequence);         { ASN_SEQUENCE }
     7: (address: TAsnIpAddress);         { ASN_IPADDRESS }
     8: (counter: TAsnCounter32);         { ASN_COUNTER32 }
     9: (gauge: TAsnGauge32);             { ASN_GAUGE32 }
    10: (ticks: TAsnTimeticks);           { ASN_TIMETICKS }
    11: (arbitrary: TAsnOpaque);          { ASN_OPAQUE }
  end;

 TAsnObjectName = TAsnObjectIdentifier;
 TAsnObjectSyntax = TAsnAny;

 PSnmpVarBind = ^TSnmpVarBind;
 TSnmpVarBind = record
   name: TAsnObjectName;
   value: TAsnObjectSyntax;
  end;

 PSnmpVarBindList = ^TSnmpVarBindList;
 TSnmpVarBindList = record
   list: PSnmpVarBind;
   len: UINT;
  end;


В главном юните есть процедура, для получения результатов SNMP запросов
procedureTMainFm.PrintVarBind(const VarBind: TSnmpVarBind);
объявлена переменная
var
 P: PByte;


затем, втеле процедуры, определяем тип ответа:

withVarBind.value do
    caseasnType of
...
     ASN_OCTETSTRING:
        begin
         A[2] := 'Octet String';
         if str.length > 0 then
          begin
           IsAscii := True;
           P := str.stream;
            fori := 0 tostr.length - 1 do
            begin
             if not (P^ in [0, 32..127]) then    // <-- ТУТ ОШИБКА!!!
              begin
               IsAscii := False;
               Break;
              end;
             Inc(P);
            end;
...
  end;


В Delphi 2007 этот код работает нормально, длина строки 89 (к примеру). В D2009 длина строки = 1, адрес str.stream равен $59 - вот и ошибка - "read from address $00000059"..

Подскажите, как с этим бороться.


tytus   (2009-08-17 16:51:00) [1]

Вот нашел решение:
{$Align 4}


tytus   (2009-08-14 16:14:00) [2]

> Дмитрий Белькевич   (14.08.09 14:12) [12]
так почему-же в Д2009 не работает сей код?
Неверно определяется указатель на данные в VarBindList.


Дмитрий Белькевич   (2009-08-14 14:12:00) [3]


> Намутили embarcadero со своим юникодом IDE и всего прочего.
> .. но все равно, хочеться разобраться, в чем тут дело...
> Какие еще есть варианты?


Намутили, если уж на то пошло, еще Майкрософт. А Эмбаркадеро проделало огромадную работу, что бы к этому всему 'счастью' приспособиться. Имейте уважение.


tytus   (2009-08-14 10:44:00) [4]

> Сергей М. ©   (14.08.09 10:16) [10]
Вполне можно было предположить, что я правильно оперировал типами строк... и никоим образом не хотел вас обмануть.
Намутили embarcadero со своим юникодом IDE и всего прочего...
но все равно, хочеться разобраться, в чем тут дело...
Какие еще есть варианты?


Сергей М.   (2009-08-14 10:16:00) [5]

Я же спросил:

> Некая переменная типа string .. ?


Ты отвечаешь:

> именно так


А теперь говоришь, что не именно и не так:

> var
>  sOID: AnsiString;


tytus   (2009-08-14 10:08:00) [6]

> Сергей М. ©   (13.08.09 20:47) [8]

> первым параметром ты передал указатель на строку в юникоде

var
 sOID: AnsiString;
begin
 sOID := '.1.3.6.1.2.1.1.1.0'; <-- это разве не ANSI ???
 SnmpMgrStrToOid(PAnsiChar(sOID), @OID);


к тому же, в процедуре PrintVarBindесть функция
SnmpUtilOidToA(@VarBind.name),которая возвращает заданный OID,
следовательно, строка передается правильно.


Сергей М.   (2009-08-13 20:47:00) [7]


> tytus   (13.08.09 17:47) [7]
> именно так


Ну а раз именно так, то первым параметром ты передал указатель на строку в юникоде, хотя ф-ция ожидает ansi-строку


tytus   (2009-08-13 17:47:00) [8]

> Сергей М. ©   (13.08.09 17:18) [5]
именно так.
> Сергей М. ©   (13.08.09 17:21) [6]
анализ есть, не писал для краткости...
  try
...
    if notSnmpMgrStrToOid(PAnsiChar(sOID), @OID) then
    begin
      RaiseException.CreateFmt('Invalid Oids, ''%s'', specified.', [sOID]);
    end;
...
  finally
   SnmpMgrClose(Session);
  end;


Сергей М.   (2009-08-13 17:21:00) [9]

И какого лешего у тебя отсутствует анализ результата. возвращаемого функциейSnmpMgrStrToOid() ? Хотя бы в целях отладки ?


Сергей М.   (2009-08-13 17:18:00) [10]


> sOID - текст эдита


Что значит "текст эдита" ?
Некая переменная типа string, в которую ты ранее сохранил значение св-ва Edit.Text ? Или что ?


tytus   (2009-08-13 15:33:00) [11]

> DVM ©   (13.08.09 15:07) [3]
да нет, ничего...
вот как отправляю запрос:
1) SnmpMgrStrToOid(PAnsiChar(sOID), @OID);где OID - TAsnObjectIdentifier, sOID - текст эдита.
2) with VarBindList do
   begin
     list :=  SnmpUtilMemAlloc(SizeOf(TSnmpVarBind));
     len := 1;
     list^.name := OID;
     list^.value.asnType := ASN_NULL;
   end;

3) RequestType := SNMP_PDU_GET;
   RetVal := SnmpMgrRequest(Session, RequestType, @VarBindList,
       @ErrorStatus, @ErrorIndex);

4) - получаем ответ
    PrintVarBind(VarBindList.list^);

Несоответствие может произойти, если компиляторы D2007 и D2009 по-разному работают.
В Д2007-ом работает, а в Д2009  - ошибка...

functionSnmpMgrRequest(session: PSnmpMgrSession; requestType: Byte; variableBindings: PSnmpVarBindList;
 errorStatus: PAsnInteger32; errorIndex: PAsnInteger32): SNMPAPI; stdcall;

functionSnmpMgrRequest; external  'mgmtapi.dll'  name  'SnmpMgrRequest';


DVM   (2009-08-13 15:07:00) [12]


> tytus

вероятно у тебя какое то несоответствие между значением str.length и реальной длиной str.stream. Случайно из строки типа string ничего туда не переносилось?


tytus   (2009-08-13 12:34:00) [13]

>DVM  (13.08.09 12:21) [1]
PAsnAny = ^TAsnAny;
TAsnAny = record
  asnType: BYTE;
  case Integer of      0: (number: TAsnInteger32);          { ASN_INTEGER, ASN_INTEGER32 }
    1: (unsigned32: TAsnUnsigned32);     { ASN_UNSIGNED32 }
    2: (counter64: TAsnCounter64);       { ASN_COUNTER64 }
    3: (str: TAsnOctetString);           { ASN_OCTETSTRING } <-- Вот ОНО - str!!!
    4: (bits: TAsnBits);                 { ASN_BITS }
    5: (obj: TAsnObjectIdentifier);      { ASN_OBJECTIDENTIFIER }
    6: (sequence: TAsnSequence);         { ASN_SEQUENCE }
    7: (address: TAsnIpAddress);         { ASN_IPADDRESS }
    8: (counter: TAsnCounter32);         { ASN_COUNTER32 }
    9: (gauge: TAsnGauge32);             { ASN_GAUGE32 }
   10: (ticks: TAsnTimeticks);           { ASN_TIMETICKS }
   11: (arbitrary: TAsnOpaque);          { ASN_OPAQUE }
end;


DVM   (2009-08-13 12:21:00) [14]

что такое str ?


Наверх

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