информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
Портрет посетителяSpanning Tree Protocol: недокументированное применение
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Очередное исследование 19 миллиардов... 
 Оптимизация ввода-вывода как инструмент... 
 Зловреды выбирают Lisp и Delphi 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
если вы видите этот текст, отключите в настройках форума использование JavaScript
ФОРУМ
все доски
FAQ
IRC
новые сообщения
site updates
guestbook
beginners
sysadmin
programming
operating systems
theory
web building
software
hardware
networking
law
hacking
gadgets
job
dnet
humor
miscellaneous
scrap
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
В паскале разберёшься? Кину тебе пример кода, который запускает Regedit и переводит его на нужную ветку в его TreeView. 07.12.06 06:37  Число просмотров: 4074
Автор: HandleX <Александр М.> Статус: The Elderman
<"чистая" ссылка> <обсуждение закрыто>

Procedure ShowServiceRegKey(aServiceName: String; FormWnd: HWND);
Type
  TRemoteBuff = Record
    Item: TTVITEM;
    aStr: Packed Array[0..820] Of Char;
  End;
  pRemoteBuff = ^TRemoteBuff;

  Function GetSFieldCount(aStr: String; Delimiter: Char = #9): DWORD;
  Var TempP: PChar;
  Begin
    TempP := PChar(aStr);
    If aStr = '' Then Result := 0
    Else Result := 1;
    While TempP^ <> #0 Do
    Begin
      If TempP^ = Delimiter Then
        Inc(Result);
      Inc(TempP);
    End;
  End;

  Function GetSField(aStr: String; anIndex: DWord; Delimiter: Char = #9): String;
  Var
    TempP: PChar;
    Counter: DWORD;
    Ind1, Ind2: Integer;
  Begin
    Counter := 0;
    Result := '';
    TempP := PChar(aStr);
    Ind1 := -1; Ind2 := -1;
    While TempP^ <> #0 Do
    Begin
      If TempP^ = Delimiter Then Inc(Counter);
      If Counter = anIndex Then
        If Ind1 = -1 Then
          Ind1 := TempP - PChar(aStr);
      If Counter > anIndex Then
      Begin
        Ind2 := TempP - PChar(aStr);
        Break;
      End;
      Inc(TempP);
    End;
    If TempP^ = #0 Then
      Ind2 := StrEnd(PChar(aStr)) - PChar(aStr);
    If Ind1 <> 0 Then Inc(Ind1);
    Result := Copy(aStr, Ind1 + 1, Ind2 - Ind1)
  End;

  Procedure ConnectHostToRegedit(aRegMainWnd: HWND; aHostName: String);

    Function GetChildEditControl(aParent: HWND): HWND;
      Function EnumProc(aHwnd: HWND; RetValue: PDWORD): BOOL; StdCall;
      Var aBuff: String[255];
      Begin
        SetLength(aBuff, GetClassName(aHwnd, @aBuff[1], 254));

        If (OSVersion.dwMajorVersion >= 5) And (OSVersion.dwMinorVersion >= 1) Then Result := Not (aBuff = 'RichEdit20W')
        Else Result := Not (aBuff = 'Edit');

        If Not Result Then
          RetValue^ := aHwnd;
      End;
    Begin
      EnumChildWindows(aParent, @EnumProc, DWORD(@Result));
    End;

    Function GetWindowClass(aWnd: HWND): String;
    Begin
      SetLength(Result, 255);
      SetLength(Result, GetClassName(aWnd, PChar(Result), Length(Result)));
    End;

  Var
    fWnd, eWnd: HWND;
    mHndl, subMenu: HMENU;
    mID: Integer;
  begin
    If aRegMainWnd = 0 Then Exit;

    mHndl := GetMenu(aRegMainWnd);
    Win32Check(mHndl <> 0);

    subMenu := GetSubMenu(mHndl, 0);
    Win32Check(SubMenu <> 0);

    If (OSVersion.dwMajorVersion >= 5) And (OSVersion.dwMinorVersion >= 1) Then mID := GetMenuItemID(SubMenu, 6)
    Else mID := GetMenuItemID(SubMenu, 3);
    Win32Check(mID > 0);

    Win32Check(PostMessage(aRegMainWnd, WM_COMMAND, mID, 0));

    Repeat
      fWnd := GetForegroundWindow;
      Sleep(50);
    Until Pos('#', GetWIndowClass(fWnd)) <> 0;

    Win32Check(fWnd <> 0);

    eWnd := GetChildEditControl(fWnd);
    Win32Check(eWnd <> 0);

    Win32Check(SendMessage(eWnd, WM_SETTEXT, 0, DWORD(PChar(aHostName))) <> 0);

    SendMessage(fWnd, WM_KEYDOWN, 13, 0);
    SendMessage(fWnd, WM_KEYUP, 13, 0);

  End;

  Function MakeFintInAnotherProcess(aProcess: THandle; aRemBuff: PRemoteBuff; aHwnd: HWND; aKey: String): Boolean;

    Procedure WriteStrToBuff(aStr: String);
    Var
      aSrc: Pointer;
      aSize, Written: DWORD;
    Begin
      aSrc := PChar(aStr);
      aSize := Length(aStr) + 1;
      If aSize > High(aRemBuff.aStr) Then
        Raise Exception.Create('String is too long!');
      Win32Check(WriteProcessMemory(aProcess, @aRemBuff^.aStr, aSrc, aSize, Written));
      Win32Check(Written = aSize);
    End;

    Function ReadStrFromBuff: String;
    Var Readed: DWORD;
    Begin
      SetLength(Result, High(aRemBuff.aStr));
      Win32Check(ReadProcessMemory(aProcess, @aRemBuff.aStr, PChar(Result), High(aRemBuff.aStr), Readed));
      Win32Check(Readed = High(aRemBuff.aStr));
      SetLength(Result, StrLen(PChar(Result)));
    End;

    Function ReadStrFromAddr(anAddr: Pointer): String;
    Var
      Readed: DWORD;
      Buff: Char;
      pTemp: Pointer;
    Begin
      pTemp := anAddr;
      Result := '';
      Repeat
        Win32Check(ReadProcessMemory(aProcess, pTemp, @Buff, 1, Readed));
        Win32Check(Readed = 1);
        If Buff <> #0 Then
          Result := Result + Buff;
        Inc(DWORD(pTemp));
      Until Buff = #0;
    End;

    Procedure WriteItemToBuff(Const Item: TTVITEM);
    Var Written: DWORD;
    Begin
      Win32Check(WriteProcessMemory(aProcess, aRemBuff, @Item, SizeOf(Item), Written));
      Win32Check(Written = SizeOf(Item));
    End;

    Procedure ReadItemFromBuff(Var Item: TTVITEM);
    Var Readed: DWORD;
    Begin
      Win32Check(ReadProcessMemory(aProcess, aRemBuff, @Item, SizeOf(Item), Readed));
      Win32Check(Readed = SizeOf(Item));
    End;

    Function GetItemText(anItem: THandle): String;
    Var ItemParams: TTVITEM;
    Begin
      ZeroMemory(@ItemParams, SizeOf(ItemParams));
      ItemParams.mask := TVIF_TEXT;
      ItemParams.hItem := HTREEITEM(anItem);
      ItemParams.pszText := @aRemBuff.aStr;
      ItemParams.cchTextMax := 400;
      WriteItemToBuff(ItemParams);
      Win32Check(TreeView_GetItem(aHwnd, aRemBuff.Item));
      ReadItemFromBuff(ItemParams);
      If ItemParams.pszText = Nil Then Result := ''
      Else
        If ItemParams.pszText = @aRemBuff.aStr Then Result := ReadStrFromBuff
        Else Result := ReadStrFromAddr(ItemParams.pszText);
    End;

    Function FindChild(aParent: THandle; aText: String): THandle;
    Var
      anItem: THandle;
      Compares: Integer;
      TempStr: String;
    Begin
      Result := 0;
      anItem := DWORD(TreeView_GetNextItem(aHwnd, HTREEITEM(aParent), TVGN_CHILD));
      If anItem = 0 Then Exit;
      Repeat
        TempStr := GetItemText(anItem);
        Compares := AnsiCompareStr(aText, TempStr);
        If Compares = 0 Then Break;
        anItem := DWORD(TreeView_GetNextSibling(aHwnd, HTREEITEM(anItem)));
      Until anItem = 0;
      If Compares = 0 Then Result := anItem;
    End;

    Function FindNextItem(fromItem: THandle; aText: String): THandle;
    Var
      anItem: THandle;
      Compares: Integer;
      TempStr: String;
    Begin
      Result := 0;
      anItem := fromItem;
      If anItem = 0 Then Exit;
      Compares := -1;
      Repeat
        anItem := SendMessage(aHwnd, TVM_GETNEXTITEM, TVGN_NEXT, anItem);
        If anItem = 0 Then Break;
        TempStr := GetItemText(anItem);
        Compares := AnsiCompareText(aText, TempStr);
      Until Compares = 0;
      If Compares = 0 Then Result := anItem;
    End;

  Var
    anItem, TempItem: THandle;
    J, Max: Integer;
    TempStr: String;
  Begin

    Max := GetSFieldCount(aKey, '\') - 1;
    Result := Max >= 0;
    If Not Result Then Exit;

    anItem := DWORD(TreeView_GetRoot(aHwnd));
    Result := anItem <> 0;
    If Not Result Then Exit;

    If (MainForm.HostName <> '') AND (UpperCase(MainForm.HostName) <> UpperCase(LocalHostName)) Then
    Begin
      ConnectHostToRegedit(GetParent(aHwnd), MainForm.HostName);
      Repeat
        Sleep(100);
        TempItem := FindNextItem(DWORD(TreeView_GetRoot(aHwnd)), MainForm.HostName);
      Until TempItem <> 0;
      anItem := TempItem;
      Result := anItem <> 0;
      If Not Result Then Exit;
    End;

    Result := TreeView_Expand(aHwnd, HTREEITEM(anItem), TVE_EXPAND);
    If Not Result Then Exit;

    For J := 0 To Max Do
    Begin
      TempStr := GetSField(aKey, J, '\');
      anItem := FindChild(anItem, TempStr);
      Result := anItem <> 0;
      If Not Result Then Exit;
      TreeView_Expand(aHwnd, HTREEITEM(anItem), TVE_EXPAND);
      If J = Max Then
        Result := TreeView_SelectItem(aHwnd, HTREEITEM(anItem)) <> HTREEITEM(0);
    End;

  End;

  Function GetWindowProcessIDByTopmostWindowClass(aClass: String; Var aWnd: HWND): DWORD;
  begin
    Result := 0;
    aWnd := FindWindow(PChar(aClass), Nil);
    If aWnd = 0 Then Exit;
    GetWindowThreadProcessID(aWnd, @Result);
  End;

  Function GetChildTreeView(aParent: HWND): HWND;
    Function EnumProc(aHwnd: HWND; RetValue: PDWORD): BOOL; StdCall;
    Var aBuff: String[255];
    Begin
      SetLength(aBuff, GetClassName(aHwnd, @aBuff[1], 254));
      Result := Not (aBuff = 'SysTreeView32');
      If Not Result Then
        RetValue^ := aHwnd;
    End;
  Begin
    EnumChildWindows(aParent, @EnumProc, DWORD(@Result));
  End;

  Function ShellExecuteAndWaitForIdle(ExePath: String): THandle;
  Var anInfo: TShellExecuteInfo;
  Begin
    ZeroMemory(@anInfo, SizeOf(anInfo));
    anInfo.cbSize := SizeOf(anInfo);
    anInfo.fMask := SEE_MASK_NOCLOSEPROCESS;
    anInfo.Wnd := FormWnd;
    anInfo.lpVerb := 'Open';
    anInfo.lpFile := PChar(ExePath);
    anInfo.nShow := SW_SHOWNORMAL;
    If Not ShellExecuteEx(@anInfo) Then Abort;
    Result := anInfo.hProcess;
    Win32Check(WaitForInputIdle(Result, INFINITE) <> $FFFFFFFF);
  End;

Var
  pID, pHndl: THandle;
  rBuff: PRemoteBuff;
  aHwnd: HWND;
Begin
  pHndl := 0;
  pID := GetWindowProcessIDByTopmostWindowClass('RegEdit_RegEdit', aHwnd);
  If pId = 0 Then
    If GetLastError = ERROR_FILE_NOT_FOUND Then
    Begin
      pHndl := ShellExecuteAndWaitForIdle('regedit.exe');
      pID := GetWindowProcessIDByTopmostWindowClass('RegEdit_RegEdit', aHwnd);
      Win32Check(pID <> 0);
    End Else RaiseLastWin32Error
  Else pHndl := OpenProcess(PROCESS_ALL_ACCESS, False, pID);
  Win32Check(pHndl <> 0);
  Try
    If IsIconic(aHwnd) Then ShowWindow(aHwnd, SW_Restore);
    SetForegroundWindow(aHwnd);

    aHwnd := GetChildTreeView(aHwnd);
    Win32Check(aHwnd <> 0);

    rBuff := VirtualAllocEx(pHndl, Nil, SizeOf(rBuff), MEM_COMMIT, PAGE_READWRITE);
    Win32Check(rBuff <> Nil);
    Try
      If Not MakeFintInAnotherProcess(pHndl, rBuff, aHwnd, 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\' + aServiceName) Then
        Raise Exception.Create('Error dialing with Regedit ;-)');
    Finally
      Win32Check(VirtualFreeEx(pHndl, rBuff, 0, MEM_RELEASE) <> Nil);
    End;
  Finally
    CloseHandle(pHndl);
  End;
End;

---
<programming>
[win32] tvm_getitem в "чужом" окне 05.12.06 12:33  
Автор: Vedrus <Serokhvostov Anton> Статус: Member
<"чистая" ссылка> <обсуждение закрыто>
Такая проблема. Нужно определить текущий элемент в контроле SysListTreeView32 в чужом окне (хэндл контрола получаю через Windows Hooks и EnumChildWindows). Попробовал через TVM_GETITEM (он же TreeView_GetItem), но это сообщение возвращает ошибку. Такое подозрение, что это сообщение нельзя использовать с чужими окнами. Вот как я делал:
	HTREEITEM hTreeItem;
	TVITEM    tvi;

	hTreeItem = TreeView_GetSelection(hwndControl);

	tvi.hItem = hTreeItem;
	tvi.mask = TVIF_TEXT;

	TreeView_GetItem(hwndControl, &tvi);


---
Вот скажи мне, вернёт тебе винда указатель на текст... 05.12.06 14:50  
Автор: HandleX <Александр М.> Статус: The Elderman
<"чистая" ссылка> <обсуждение закрыто>
А теперь давай порассуждаем...

На что указатель? Верно, на память. В адресном пространстве какого процесса? Как ты думаешь, вот если ты бы писал венды, стал бы ты парить моск, копируя букаффки из адресного пространства одного процеса в адресное пространство другого (насколько я понимаю, у тебя хендл окна ДРУГОГО процесса)? Вот я бы не стал. Поскольку 99,9999 использования этого сообщения наблюдается в своём процессе со своими контролами -)) И программеры M$ тоже себя этим не стали утруждать. Поэтому берём VirtualAllocEx (аллоцируем память под букаффки в читаемом процессе), шлём соответств. мессидж в чужое окно с соотв. указателем на память, валидном в ТОМ процессе, а потом читаем чужое адресное пространство с помощью ReadProcessMemory(). И не забываем, что в 9x-ME виндах этих функций нет.

Удачи.
Вот пробую сделать то же самое, но уже в своём процессе и законном обработчике окна. Тоже названия веток не определяются. Хэндл проверял - не ноль. Где я опять туплю? 07.12.06 03:36  
Автор: Vedrus <Serokhvostov Anton> Статус: Member
Отредактировано 07.12.06 03:54  Количество правок: 2
<"чистая" ссылка> <обсуждение закрыто>
В паскале разберёшься? Кину тебе пример кода, который запускает Regedit и переводит его на нужную ветку в его TreeView. 07.12.06 06:37  
Автор: HandleX <Александр М.> Статус: The Elderman
<"чистая" ссылка> <обсуждение закрыто>

Procedure ShowServiceRegKey(aServiceName: String; FormWnd: HWND);
Type
  TRemoteBuff = Record
    Item: TTVITEM;
    aStr: Packed Array[0..820] Of Char;
  End;
  pRemoteBuff = ^TRemoteBuff;

  Function GetSFieldCount(aStr: String; Delimiter: Char = #9): DWORD;
  Var TempP: PChar;
  Begin
    TempP := PChar(aStr);
    If aStr = '' Then Result := 0
    Else Result := 1;
    While TempP^ <> #0 Do
    Begin
      If TempP^ = Delimiter Then
        Inc(Result);
      Inc(TempP);
    End;
  End;

  Function GetSField(aStr: String; anIndex: DWord; Delimiter: Char = #9): String;
  Var
    TempP: PChar;
    Counter: DWORD;
    Ind1, Ind2: Integer;
  Begin
    Counter := 0;
    Result := '';
    TempP := PChar(aStr);
    Ind1 := -1; Ind2 := -1;
    While TempP^ <> #0 Do
    Begin
      If TempP^ = Delimiter Then Inc(Counter);
      If Counter = anIndex Then
        If Ind1 = -1 Then
          Ind1 := TempP - PChar(aStr);
      If Counter > anIndex Then
      Begin
        Ind2 := TempP - PChar(aStr);
        Break;
      End;
      Inc(TempP);
    End;
    If TempP^ = #0 Then
      Ind2 := StrEnd(PChar(aStr)) - PChar(aStr);
    If Ind1 <> 0 Then Inc(Ind1);
    Result := Copy(aStr, Ind1 + 1, Ind2 - Ind1)
  End;

  Procedure ConnectHostToRegedit(aRegMainWnd: HWND; aHostName: String);

    Function GetChildEditControl(aParent: HWND): HWND;
      Function EnumProc(aHwnd: HWND; RetValue: PDWORD): BOOL; StdCall;
      Var aBuff: String[255];
      Begin
        SetLength(aBuff, GetClassName(aHwnd, @aBuff[1], 254));

        If (OSVersion.dwMajorVersion >= 5) And (OSVersion.dwMinorVersion >= 1) Then Result := Not (aBuff = 'RichEdit20W')
        Else Result := Not (aBuff = 'Edit');

        If Not Result Then
          RetValue^ := aHwnd;
      End;
    Begin
      EnumChildWindows(aParent, @EnumProc, DWORD(@Result));
    End;

    Function GetWindowClass(aWnd: HWND): String;
    Begin
      SetLength(Result, 255);
      SetLength(Result, GetClassName(aWnd, PChar(Result), Length(Result)));
    End;

  Var
    fWnd, eWnd: HWND;
    mHndl, subMenu: HMENU;
    mID: Integer;
  begin
    If aRegMainWnd = 0 Then Exit;

    mHndl := GetMenu(aRegMainWnd);
    Win32Check(mHndl <> 0);

    subMenu := GetSubMenu(mHndl, 0);
    Win32Check(SubMenu <> 0);

    If (OSVersion.dwMajorVersion >= 5) And (OSVersion.dwMinorVersion >= 1) Then mID := GetMenuItemID(SubMenu, 6)
    Else mID := GetMenuItemID(SubMenu, 3);
    Win32Check(mID > 0);

    Win32Check(PostMessage(aRegMainWnd, WM_COMMAND, mID, 0));

    Repeat
      fWnd := GetForegroundWindow;
      Sleep(50);
    Until Pos('#', GetWIndowClass(fWnd)) <> 0;

    Win32Check(fWnd <> 0);

    eWnd := GetChildEditControl(fWnd);
    Win32Check(eWnd <> 0);

    Win32Check(SendMessage(eWnd, WM_SETTEXT, 0, DWORD(PChar(aHostName))) <> 0);

    SendMessage(fWnd, WM_KEYDOWN, 13, 0);
    SendMessage(fWnd, WM_KEYUP, 13, 0);

  End;

  Function MakeFintInAnotherProcess(aProcess: THandle; aRemBuff: PRemoteBuff; aHwnd: HWND; aKey: String): Boolean;

    Procedure WriteStrToBuff(aStr: String);
    Var
      aSrc: Pointer;
      aSize, Written: DWORD;
    Begin
      aSrc := PChar(aStr);
      aSize := Length(aStr) + 1;
      If aSize > High(aRemBuff.aStr) Then
        Raise Exception.Create('String is too long!');
      Win32Check(WriteProcessMemory(aProcess, @aRemBuff^.aStr, aSrc, aSize, Written));
      Win32Check(Written = aSize);
    End;

    Function ReadStrFromBuff: String;
    Var Readed: DWORD;
    Begin
      SetLength(Result, High(aRemBuff.aStr));
      Win32Check(ReadProcessMemory(aProcess, @aRemBuff.aStr, PChar(Result), High(aRemBuff.aStr), Readed));
      Win32Check(Readed = High(aRemBuff.aStr));
      SetLength(Result, StrLen(PChar(Result)));
    End;

    Function ReadStrFromAddr(anAddr: Pointer): String;
    Var
      Readed: DWORD;
      Buff: Char;
      pTemp: Pointer;
    Begin
      pTemp := anAddr;
      Result := '';
      Repeat
        Win32Check(ReadProcessMemory(aProcess, pTemp, @Buff, 1, Readed));
        Win32Check(Readed = 1);
        If Buff <> #0 Then
          Result := Result + Buff;
        Inc(DWORD(pTemp));
      Until Buff = #0;
    End;

    Procedure WriteItemToBuff(Const Item: TTVITEM);
    Var Written: DWORD;
    Begin
      Win32Check(WriteProcessMemory(aProcess, aRemBuff, @Item, SizeOf(Item), Written));
      Win32Check(Written = SizeOf(Item));
    End;

    Procedure ReadItemFromBuff(Var Item: TTVITEM);
    Var Readed: DWORD;
    Begin
      Win32Check(ReadProcessMemory(aProcess, aRemBuff, @Item, SizeOf(Item), Readed));
      Win32Check(Readed = SizeOf(Item));
    End;

    Function GetItemText(anItem: THandle): String;
    Var ItemParams: TTVITEM;
    Begin
      ZeroMemory(@ItemParams, SizeOf(ItemParams));
      ItemParams.mask := TVIF_TEXT;
      ItemParams.hItem := HTREEITEM(anItem);
      ItemParams.pszText := @aRemBuff.aStr;
      ItemParams.cchTextMax := 400;
      WriteItemToBuff(ItemParams);
      Win32Check(TreeView_GetItem(aHwnd, aRemBuff.Item));
      ReadItemFromBuff(ItemParams);
      If ItemParams.pszText = Nil Then Result := ''
      Else
        If ItemParams.pszText = @aRemBuff.aStr Then Result := ReadStrFromBuff
        Else Result := ReadStrFromAddr(ItemParams.pszText);
    End;

    Function FindChild(aParent: THandle; aText: String): THandle;
    Var
      anItem: THandle;
      Compares: Integer;
      TempStr: String;
    Begin
      Result := 0;
      anItem := DWORD(TreeView_GetNextItem(aHwnd, HTREEITEM(aParent), TVGN_CHILD));
      If anItem = 0 Then Exit;
      Repeat
        TempStr := GetItemText(anItem);
        Compares := AnsiCompareStr(aText, TempStr);
        If Compares = 0 Then Break;
        anItem := DWORD(TreeView_GetNextSibling(aHwnd, HTREEITEM(anItem)));
      Until anItem = 0;
      If Compares = 0 Then Result := anItem;
    End;

    Function FindNextItem(fromItem: THandle; aText: String): THandle;
    Var
      anItem: THandle;
      Compares: Integer;
      TempStr: String;
    Begin
      Result := 0;
      anItem := fromItem;
      If anItem = 0 Then Exit;
      Compares := -1;
      Repeat
        anItem := SendMessage(aHwnd, TVM_GETNEXTITEM, TVGN_NEXT, anItem);
        If anItem = 0 Then Break;
        TempStr := GetItemText(anItem);
        Compares := AnsiCompareText(aText, TempStr);
      Until Compares = 0;
      If Compares = 0 Then Result := anItem;
    End;

  Var
    anItem, TempItem: THandle;
    J, Max: Integer;
    TempStr: String;
  Begin

    Max := GetSFieldCount(aKey, '\') - 1;
    Result := Max >= 0;
    If Not Result Then Exit;

    anItem := DWORD(TreeView_GetRoot(aHwnd));
    Result := anItem <> 0;
    If Not Result Then Exit;

    If (MainForm.HostName <> '') AND (UpperCase(MainForm.HostName) <> UpperCase(LocalHostName)) Then
    Begin
      ConnectHostToRegedit(GetParent(aHwnd), MainForm.HostName);
      Repeat
        Sleep(100);
        TempItem := FindNextItem(DWORD(TreeView_GetRoot(aHwnd)), MainForm.HostName);
      Until TempItem <> 0;
      anItem := TempItem;
      Result := anItem <> 0;
      If Not Result Then Exit;
    End;

    Result := TreeView_Expand(aHwnd, HTREEITEM(anItem), TVE_EXPAND);
    If Not Result Then Exit;

    For J := 0 To Max Do
    Begin
      TempStr := GetSField(aKey, J, '\');
      anItem := FindChild(anItem, TempStr);
      Result := anItem <> 0;
      If Not Result Then Exit;
      TreeView_Expand(aHwnd, HTREEITEM(anItem), TVE_EXPAND);
      If J = Max Then
        Result := TreeView_SelectItem(aHwnd, HTREEITEM(anItem)) <> HTREEITEM(0);
    End;

  End;

  Function GetWindowProcessIDByTopmostWindowClass(aClass: String; Var aWnd: HWND): DWORD;
  begin
    Result := 0;
    aWnd := FindWindow(PChar(aClass), Nil);
    If aWnd = 0 Then Exit;
    GetWindowThreadProcessID(aWnd, @Result);
  End;

  Function GetChildTreeView(aParent: HWND): HWND;
    Function EnumProc(aHwnd: HWND; RetValue: PDWORD): BOOL; StdCall;
    Var aBuff: String[255];
    Begin
      SetLength(aBuff, GetClassName(aHwnd, @aBuff[1], 254));
      Result := Not (aBuff = 'SysTreeView32');
      If Not Result Then
        RetValue^ := aHwnd;
    End;
  Begin
    EnumChildWindows(aParent, @EnumProc, DWORD(@Result));
  End;

  Function ShellExecuteAndWaitForIdle(ExePath: String): THandle;
  Var anInfo: TShellExecuteInfo;
  Begin
    ZeroMemory(@anInfo, SizeOf(anInfo));
    anInfo.cbSize := SizeOf(anInfo);
    anInfo.fMask := SEE_MASK_NOCLOSEPROCESS;
    anInfo.Wnd := FormWnd;
    anInfo.lpVerb := 'Open';
    anInfo.lpFile := PChar(ExePath);
    anInfo.nShow := SW_SHOWNORMAL;
    If Not ShellExecuteEx(@anInfo) Then Abort;
    Result := anInfo.hProcess;
    Win32Check(WaitForInputIdle(Result, INFINITE) <> $FFFFFFFF);
  End;

Var
  pID, pHndl: THandle;
  rBuff: PRemoteBuff;
  aHwnd: HWND;
Begin
  pHndl := 0;
  pID := GetWindowProcessIDByTopmostWindowClass('RegEdit_RegEdit', aHwnd);
  If pId = 0 Then
    If GetLastError = ERROR_FILE_NOT_FOUND Then
    Begin
      pHndl := ShellExecuteAndWaitForIdle('regedit.exe');
      pID := GetWindowProcessIDByTopmostWindowClass('RegEdit_RegEdit', aHwnd);
      Win32Check(pID <> 0);
    End Else RaiseLastWin32Error
  Else pHndl := OpenProcess(PROCESS_ALL_ACCESS, False, pID);
  Win32Check(pHndl <> 0);
  Try
    If IsIconic(aHwnd) Then ShowWindow(aHwnd, SW_Restore);
    SetForegroundWindow(aHwnd);

    aHwnd := GetChildTreeView(aHwnd);
    Win32Check(aHwnd <> 0);

    rBuff := VirtualAllocEx(pHndl, Nil, SizeOf(rBuff), MEM_COMMIT, PAGE_READWRITE);
    Win32Check(rBuff <> Nil);
    Try
      If Not MakeFintInAnotherProcess(pHndl, rBuff, aHwnd, 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\' + aServiceName) Then
        Raise Exception.Create('Error dialing with Regedit ;-)');
    Finally
      Win32Check(VirtualFreeEx(pHndl, rBuff, 0, MEM_RELEASE) <> Nil);
    End;
  Finally
    CloseHandle(pHndl);
  End;
End;

---
В задаче обошлось текущим процессом. Был ещё один касяк у... 26.12.06 17:55  
Автор: Vedrus <Serokhvostov Anton> Статус: Member
<"чистая" ссылка> <обсуждение закрыто>
В задаче обошлось текущим процессом. Был ещё один касяк у меня: в pszText не ложил ссылку на существующий буфер
	char   buf[200];
	TVITEM tvi;
	...........
	tvi.hItem = TreeView_GetSelection(hwndTree);
	tvi.mask  = TVIF_TEXT;					// команда на получение текста
	tvi.cchTextMax = 40;					// максимум 40 символов
	tvi.pszText = buf;					// буфер для текста
	TreeView_GetItem(hwndTree, &tvi)

---
Спасибо за код. Читая его у себя касяк и нашёл.
Там все еще забавнее 05.12.06 15:16  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка> <обсуждение закрыто>
> стали утруждать. Поэтому берём VirtualAllocEx (аллоцируем
> память под букаффки в читаемом процессе), шлём соответств.
> мессидж в чужое окно с соотв. указателем на память,
> валидном в ТОМ процессе, а потом читаем чужое адресное
> пространство с помощью ReadProcessMemory(). И не забываем,

Как минимум WM_GETTEXT (скорее всего и common control-ы тоже) смотрит чтобы окно принадлежало тому же процессу, что и поток, пославший оный gettext. Если процессы разные - текст не копируется вообще. Единственный реальный способ - CreateRemoteThread-выделение памяти-получение строки-копирование через WriteProcessMemory в родительский процесс
В своё время писал софтину, которая открывает regedit на нужном ключе реестра. Там нет RemoteThread, есть только то, о чём я говорил выше. 06.12.06 08:13  
Автор: HandleX <Александр М.> Статус: The Elderman
<"чистая" ссылка> <обсуждение закрыто>
Ну значит Common Control-ы не проверяют процесс. А зря. Если любой процесс может выставить буфером-приемником любой адрес в адресном пространстве жертвы, то завалить такую апликуху - раз плюнуть 06.12.06 15:04  
Автор: amirul <Serge> Статус: The Elderman
<"чистая" ссылка> <обсуждение закрыто>
1




Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2025 Dmitry Leonov   Page build time: 0 s   Design: Vadim Derkach