Re[5]: Добавление постоянного маршрута под Vista и 7
От: Maks1509 Россия http://mv-software.narod.ru
Дата: 14.07.10 17:36
Оценка:
Здравствуйте, MTimur, Вы писали:

MT>Не совсем понятно, что не работает именно в висте.

MT>Не сохраняется маршрут? — Тогда здесь:
MT>

MIB_IPPROTO_NETMGMT

MT>A static route. This value is used to identify route information for IP routing set through network management such as the Dynamic Host Configuration Protocol (DCHP), the Simple Network Management Protocol (SNMP), or by calls to the CreateIpForwardEntry, DeleteIpForwardEntry, or SetIpForwardEntry functions.


MT>Или CreateIpForwardEntry с ошибкой отрабатывает? — Тогда там и искать ошибку, например, вот такая "мелочь" может быть:


MT>

On Windows Vista and Windows Server 2008, the route metric specified in the dwForwardMetric1 member of the MIB_IPFORWARDROW structure represents a combination of the route metric added to the interface metric specified in the Metric member of the MIB_IPINTERFACE_ROW structure of the associated interface. So the dwForwardMetric1 member of the MIB_IPFORWARDROW structure should be equal to or greater than Metric member of the associated MIB_IPINTERFACE_ROW structure. If an application would like to set the route metric to 0, then the dwForwardMetric1 member of the MIB_IPFORWARDROW structure should be set equal to the value of the interface metric specified in the Metric member of the associated MIB_IPINTERFACE_ROW structure. An application can retrieve the interface metric by calling the GetIpInterfaceEntry function.


MT>Если не ошибаюсь, этот самый dwForwardMetric1 должен быть не меньше магической 10.


Все превосходно сохраняется в таблице маршрутизации, но добавленный маршрут существует до первой перезагрузки. Временным решением проверяю версию системы и если dwMajorVersion соответствует вистовскому или семерочному, просто запускаю системный route.exe. Впринципе код полноценно работоспособен и на этих системах, но он бесполезен без ключей HKLM\SYSTEM\ControlSet001\Control\Nsi\{eb004a00-9b1a-11d4-9123-0050047759bc}\16 и HKLM\SYSTEM\CurrentControlSet\Control\Nsi\{eb004a00-9b1a-11d4-9123-0050047759bc}\16, ведь только по ним система определяет маршруты как постоянные.

function CreateForwardEntry(pszDest, pszMask, pszHop: WideString): DWORD;
const
  fmtLine: WideString = 'route ADD %s MASK %s %s -P';
  fmtSkey: WideString = '%s,%s,%s,1';
  fmtHkey: WideString = 'SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\PersistentRoutes';
var
  pszText : WideString;
  si      : TStartupInfoW;
  pi      : TProcessInformation;
  dwError : DWORD;
  //
  pRoute  : MIB_IPFORWARDROW;
  dwIndex : DWORD;
  dwMetric: DWORD;
  //
  regKey  : HKEY;
  cbData  : DWORD;
  Dispos  : DWORD;
  //
  dwDest  : IPAddr;
  dwMask  : IPAddr;
  dwHop   : IPAddr;
begin

  Result := ERROR_INVALID_FUNCTION;

  // в системах Windows Vista и Windows 7 теперь необходимо добавлять двоичные
  // данные в ключ (не сохраняется постоянный маршрут):
  // HKLM\SYSTEM\CurrentControlSet\Control\Nsi\{GUID}\16\<binary value>
  // http://support.microsoft.com/kb/2011762
  // временное решение - запускаем системное приложение route.exe и проверяем
  // код выхода процесса.

  if (osvi.dwMajorVersion >= 6) then
  begin

    pszText := FormatW(fmtLine, [pszDest, pszMask, pszHop]);

    ZeroMemory(@si, SizeOf(TStartupInfoW));
    with si do
    begin
      cb          := SizeOf(TStartupInfoW);
      dwFlags     := STARTF_USESHOWWINDOW;
      wShowWindow := SW_HIDE;
    end;

    if CreateProcessW(nil, LPWSTR(pszText), nil, nil, FALSE, 0, nil, nil, si, pi) then
    begin

      WaitforSingleObject(pi.hProcess, INFINITE);
      GetExitCodeProcess(pi.hProcess, Result);
      CloseHandle(pi.hProcess);
      CloseHandle(pi.hThread);

    end;

  end
  else
  begin

    dwDest := inet_addr(LPTSTR(WideStringToAnsi(pszDest, CP_ACP)));
    dwMask := inet_addr(LPTSTR(WideStringToAnsi(pszMask, CP_ACP)));
    dwHop  := inet_addr(LPTSTR(WideStringToAnsi(pszHop, CP_ACP)));

    dwIndex := DWORD(-1);

    try

      dwError := GetBestInterface(dwDest, dwIndex);
      if (dwError = ERROR_SUCCESS) then
        begin

        if (dwIndex <> DWORD(-1)) then
        try

          dwError := GetBestRoute(dwDest, 0, pRoute);
          if (dwError = NO_ERROR) then
          try

            dwMetric := pRoute.dwForwardMetric1;

            ZeroMemory(@pRoute, SizeOf(MIB_IPFORWARDROW));

            with pRoute do
            begin
              dwForwardDest      := dwDest;
              dwForwardMask      := dwMask;
              dwForwardPolicy    := 0;
              dwForwardNextHop   := dwHop;
              dwForwardIfIndex   := dwIndex;
              dwForwardType      := MIB_IPROUTE_TYPE_DIRECT;
              dwForwardProto     := PROTO_IP_NETMGMT;
              dwForwardAge       := 0;
              dwForwardNextHopAS := 0;
              dwForwardMetric1   := dwMetric;
              dwForwardMetric2   := DWORD(-1);
              dwForwardMetric3   := DWORD(-1);
              dwForwardMetric4   := DWORD(-1);
              dwForwardMetric5   := DWORD(-1);
            end;

            dwError := CreateIpForwardEntry(@pRoute);
            if (dwError = NO_ERROR) then
            try

              cbData := {(lstrlenW(LPWSTR(pszText)) + 1) * SizeOf(WideChar)}2;

              pszText := FormatW(fmtSkey, [pszDest, pszMask, pszHop]);

              dwError := RegCreateKeyExW(HKEY_LOCAL_MACHINE, LPWSTR(fmtHkey), 0,
                nil, REG_OPTION_NON_VOLATILE, KEY_WRITE, nil, regKey, @Dispos);

              if (dwError = ERROR_SUCCESS) then
              try

                dwError := RegSetValueExW(regKey, LPWSTR(pszText), 0, REG_SZ,
                  LPWSTR(WideString('')), cbData);

                Result := dwError;

              finally
                RegCloseKey(regKey);
              end;

            finally
            end;

          except
          end;

        except
        end;

      end;

    except
    end;

  end;

end;
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.