Сейчас на форуме: tyns777, zombi-vadim (+4 невидимых)

 eXeL@B —› Программирование —› Помогите допортировать функцию из C в Pascal...
Посл.ответ Сообщение

Ранг: 36.8 (посетитель)
Активность: 0.020
Статус: Участник

Создано: 25 ноября 2007 11:03
· Личное сообщение · #1

Всем привет... Есть API-функция SHBindToParent, однако в Windows 98 она отсутствует. В сети нашел исходник на С, вот он:
HRESULT SHBindToParent(
LPCITEMIDLIST pidl,
REFIID riid,
VOID** ppv,
LPCITEMIDLIST* ppidlLast)
{
if (!ppv)
return E_POINTER;

// There must be at least one item ID.
if (!pidl || !pidl->mkid.cb)
return E_INVALIDARG;

// Get the root folder.
IShellFolderPtr desktop;
HRESULT hr = SHGetDesktopFolder(&desktop);
if (FAILED(hr))
return hr;

// Walk to the penultimate item ID.
LPCITEMIDLIST marker = pidl;
for (;;)
{ !!!!!!!!!!!!!!!! Вот в этом месте я завис !!!!!!!!!!!!!!!!
LPCITEMIDLIST next = reinterpret_cast<LPCITEMIDLIST>(
marker->mkid.abID - sizeof(marker->mkid.cb) + marker->mkid.cb);
if (!next->mkid.cb)
break;
marker = next;
};

if (marker == pidl)
{
// There was only a single item ID, so bind to the root folder.
hr = desktop->QueryInterface(riid, ppv);
}
else
{
// Copy the ID list, truncating the last item.
int length = marker->mkid.abID - pidl->mkid.abID;
if (LPITEMIDLIST parent_id = reinterpret_cast<LPITEMIDLIST>(
malloc(length + sizeof(pidl->mkid.cb))))
{
LPBYTE raw_data = reinterpret_cast<LPBYTE>(parent_id);
memcpy(raw_data, pidl, length);
memset(raw_data + length, 0, sizeof(pidl->mkid.cb));
hr = desktop->BindToObject(parent_id, 0, riid, ppv);
free(parent_id);
}
else
return E_OUTOFMEMORY;
}

// Return a pointer to the last item ID.
if (ppidlLast)
*ppidlLast = marker;

return hr;
}


Помогите допортировать его в Pascal. Вот что я уже сделал:
function SHBindToParent(pidl: PItemIDList; const riid: TIID;
var ppv: Pointer; out ppidlLast): HResult;
var
desktop : IShellFolder;
hr : HRESULT;
marker, next : PITEMIDLIST;
length : integer;
parent_id : PITEMIDLIST;
raw_data : PBYTE;
begin
if ppv = nil then
Result := E_POINTER;

// There must be at least one item ID.
if (pidl = nil) or (pidl.mkid.cb = 0) then
Result := E_INVALIDARG;

// Get the root folder.
hr := SHGetDesktopFolder(desktop);
if hr <> S_OK then
Result := hr;

// Walk to the penultimate item ID.
marker := pidl;
(* while true do !!!!!!!!!!!!!!!! Вот в этом месте я завис !!!!!!!!!!!!!!!!
begin
length := marker.mkid.abID[0] - sizeof(marker.mkid.cb);
next := PITEMIDLIST(length + marker.mkid.cb);
try
if next.mkid.cb = 0 then
begin
break;
end;
except
break;
end;
marker := next;
end;*)

if marker = pidl then
begin
// There was only a single item ID, so bind to the root folder.
hr := desktop.QueryInterface(riid, ppv);
end
else
begin
// Copy the ID list, truncating the last item.
length := marker.mkid.abID[0] - pidl.mkid.abID[0];
parent_id := PITEMIDLIST(_malloc(length + sizeof(pidl.mkid.cb)));
if parent_id <> nil then
begin
raw_data := PBYTE(parent_id);
_memcmp(raw_data, pidl, length);
_memset(raw_data, 0, sizeof(pidl.mkid.cb) + length);
hr := desktop.BindToObject(parent_id, 0, riid, ppv);
_free(parent_id);
end
else
Result := E_OUTOFMEMORY;
end;

// Return a pointer to the last item ID.
if hr = S_OK then
ppidlLast := marker;

Result := hr;
end;


Все функции типа _malloc и прочие беру из заголовочного файла MSVCRT.PAS...



Ранг: 260.2 (наставник)
Активность: 0.190
Статус: Участник

Создано: 25 ноября 2007 12:09
· Личное сообщение · #2

NeoTall пишет:
marker, next : PITEMIDLIST;

NeoTall пишет:
if next.mkid.cb = 0 then
begin
break;
end;

брр, next это указатель, наверно надо так:
if next.mkid.cb^=0 then
break;



Ранг: 36.8 (посетитель)
Активность: 0.020
Статус: Участник

Создано: 25 ноября 2007 12:36
· Личное сообщение · #3

Ну, уж тогда: if next^.mkid.cb = 0 then. Только вопрос не в этом вообще-то... Я не могу next получить из marker...



Ранг: 54.0 (постоянный)
Активность: 0.020
Статус: Участник

Создано: 25 ноября 2007 12:58
· Личное сообщение · #4

Вроде так будет правильно:

while true do begin
next := PItemIDList(cardinal(addr(marker^.mkid.abID)) - sizeof(marker^.mkid.cb) + marker^.mkid.cb);
if next^.mkid.cb = 0 then break;
marker := next;
end;

Изврат конечно, хотя, вдруг проканает?



Ранг: 260.2 (наставник)
Активность: 0.190
Статус: Участник

Создано: 25 ноября 2007 13:25
· Личное сообщение · #5

NeoTall пишет:
Ну, уж тогда: if next^.mkid.cb = 0

ну да точно, ещё не проснулсо..
гы, так ты везде не туда обращаешься!
NeoTall пишет:
if (pidl = nil) or (pidl.mkid.cb = 0) then

и Pro100ya тебе показал ещё..




Ранг: 387.4 (мудрец)
Активность: 0.170
Статус: Участник
системщик

Создано: 26 ноября 2007 03:06
· Личное сообщение · #6

NeoTall, слуш, а может просто скомпиль и прицкпи .obj? На худой конец попроси компилер вывести тебе listing и воткни asm.


 eXeL@B —› Программирование —› Помогите допортировать функцию из C в Pascal...
:: Ваш ответ
Жирный  Курсив  Подчеркнутый  Перечеркнутый  {mpf5}  Код  Вставить ссылку 
:s1: :s2: :s3: :s4: :s5: :s6: :s7: :s8: :s9: :s10: :s11: :s12: :s13: :s14: :s15: :s16:


Максимальный размер аттача: 500KB.
Ваш логин: german1505 » Выход » ЛС
   Для печати Для печати