Удаление и копирование reparse point

Как копировать точку повторной обработки или удалить reparse point




При удалении reparse данных из файла у него пропадает атрибут FILE_ATTRIBUTE_REPARSE_POINT и он перестаёт быть точкой повторной обработки. Файл или каталог становится обратно обычным объектом файловой системы.

О создании ссылок читайте статью Создание символьной ссылки Windows на C/C++.

Удаление reparse

Удаление данных точки повторной обработки выполняется через вызов DeviceIoControl с параметром FSCTL_DELETE_REPARSE_POINT. Перед вызовом DeviceIoControl требуется узнать значение ReparseTag, то есть тип точки повторной обработки. Этот тип тоже указывается при вызове функции.

Чтобы получить ReparseTag нужно вызвать DeviceIoControl с параметром FSCTL_GET_REPARSE_POINT, и вынуть его из структуры REPARSE_DATA_BUFFER или REPARSE_GUID_DATA_BUFFER (неважно, так как поле ReparseTag в них находится по одному смещению).

HANDLE OpenLinkHandle(LPCTSTR pszPath) 
{  
  return 
  CreateFile(pszPath, GENERIC_READ | GENERIC_WRITE,
    0, NULL, OPEN_EXISTING, 
  FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL);
}

DWORD GetReparseDataTag(LPCTSTR src)
{
  char reparse_buf[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
    PREPARSE_DATA_BUFFER rd = (PREPARSE_DATA_BUFFER) reparse_buf;
  DWORD dwRet;
  HANDLE hSrc;

  // Открыть и получить reparse-данные из первого файла или каталога

  hSrc = OpenLinkHandle(src);
  
  if (hSrc == INVALID_HANDLE_VALUE) 
  {
    return FALSE;
  }

  if (!DeviceIoControl(hSrc, FSCTL_GET_REPARSE_POINT, 
    NULL, 0, rd, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &dwRet, NULL))
  {
    return FALSE;
  }
  
  CloseHandle(hSrc);
  return rd->ReparseTag;
}

После того, как с помощью функции GetReparseDataTag получен тег, означающий тип точки повторной обработки, можно удалить из файла reparse информацию. Делается это с помощью следующей функции:

BOOL DeleteReparseData(LPCTSTR src, DWORD reparse_tag)
{
  REPARSE_GUID_DATA_BUFFER rd;
  HANDLE hDel = OpenLinkHandle(src);
  DWORD dwRet;

  if (hDel == INVALID_HANDLE_VALUE) 
  {
    return FALSE;
  }
  
  ZeroMemory(&rd, REPARSE_GUID_DATA_BUFFER_HEADER_SIZE);
  rd.ReparseTag = reparse_tag;

  if (!DeviceIoControl(hDel, FSCTL_DELETE_REPARSE_POINT, 
      &rd, REPARSE_GUID_DATA_BUFFER_HEADER_SIZE, NULL, 0,
      &dwRet, NULL))
  {
    return FALSE;
  }
  
  CloseHandle(hDel);
  return TRUE;
}

Копирование данных

Копирование данных заключается в получении reparse-данных в REPARSE_DATA_BUFFER или REPARSE_GUID_DATA_BUFFER, с помощью DeviceIoControl FSCTL_GET_REPARSE_POINT и записи этих данных в другой файл с помощью FSCTL_SET_REPARSE_POINT. Всё так же, как и при создании reparse point, только буфер формируется не вручную, а копируется из существующего файла.

По теме точек повторной обработки также есть следующее:



Автор: амдф
Дата: 08.02.2011


При копировании материалов хорошим тоном будет указание авторства и ссылка на сайт.