Basically, all you need to do is call DAPIRead, obtain two DAPI_ENTRY pointers (one with attribute names and the other with their values), then traverse them and dump whatever you'll find to the screen.
The following sample demonstrates how this may be accomplished.
function DumpItemAttributes(pdeAttributes, pdeValues:PDAPI_ENTRY):TStrings;
var
i,
iCount:Cardinal;
pAttributeLoc,
pdeValuesLoc:PATT_VALUE;
begin
Result:=TstringList.Create;
// We assume both pointers to be valid
if (not Assigned(pdeAttributes) or not Assigned(pdeValues)) then
begin
ShowMessage('ERROR! One of DAPI_ENTRY pointers is NIL...');
exit;
end;
// We also assume number of attributes and values equal
if (pdeAttributes.unAttributes <> pdeValues.unAttributes ) then
begin
ShowMessage('ERROR! Number of attributes is not equal to number of values...');
Exit;
end;
iCount := pdeAttributes.unAttributes;
ShowMessage('Total number of attributes: ' + IntToStr(iCount));
for i:= 0 to iCount-1 do
begin
pAttributeLoc := PATT_VALUE(ULONG(pdeAttributes.rgEntryValues) + (sizeof(ATT_VALUE)*i));
pdeValuesLoc := PATT_VALUE(ULONG(pdeValues.rgEntryValues) + (sizeof(ATT_VALUE)*i));
case pdeValuesLoc.DapiType of
DAPI_NO_VALUE: Result.Add(StrPas(pAttributeLoc.Value.pszA) + #0 +'NO VALUE');
DAPI_INT: Result.Add(StrPas(pAttributeLoc.Value.pszA) + #0 +
IntToStr(pdeValuesLoc.Value.iValue));
DAPI_STRING8:Result.Add(StrPas(pAttributeLoc.Value.pszA) + #0 +StrPas(pdeValuesLoc.Value.pszA));
DAPI_UNICODE:Result.Add(StrPas(pAttributeLoc.Value.pszA) + #0 +'Unicode string here...');
DAPI_BOOL:
if (pAttributeLoc.Value._bool) then
Result.Add(StrPas(pAttributeLoc.Value.pszA) + #0 +'TRUE')
else
Result.Add(StrPas(pAttributeLoc.Value.pszA) + #0 +'FALSE');
DAPI_BINARY:Result.Add(StrPas(pAttributeLoc.Value.pszA) + #0 +'Binary Data Here...');
else
// We are not supposed to get here...
Result.Add(StrPas(pAttributeLoc.Value.pszA) + #0 +'We are not supposed to get here...');
end;
end;
end;
You may insert a call to this function after you have successfully called DAPIRead. It will conveniently dump all retrieved data to the screen. For the sake of experiment I have done this for my Addr-Type object and was amazed to see 50 (!) attributes dumped, many of them with no values (DAPI_NO_VALUE). However, important attributes such as "Obj-Dist-Name" (Object distinguished name), "Admin-Display-Name" and some others have been dumped with values that make sense.
Anyway, using DAPI_READ_DEFINED_ATTRIBUTES for an Addr-Type object have returned 15 attributes to me, which is equal to what Exchange Admin lists when asked for raw properties. The only difference between Exchange Administrator output and that of the DumpItemAttributes function seems to be the Obj-Class attribute. Exchange Admin lists it as "Object-Class" which is obviously similar but not quite the same. Also, the value for Object-Class is binary and the dialog allows you to choose between two values there. Contrary to this, the Obj-Class attribute is text and the value is "Addr-Type".
We have DELPHI Class that process reading and writing with DAPI.