Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > SetFileValidData


Автор: hash_2000 9.10.2009, 06:31
Доброго времени суток!
подскажите ктонибудь кто пользовался функцией SetFileValidData  .... как ей пользоваться !!!? smile ... 
при использованиии всегда возвращает ошибку выполнения GetLastError() == ERROR_PRIVILEGE_NOT_HELD
в МСДН написано что должны быть установлены привелегии SE_MANAGE_VOLUME_NAME , не знаю где их устанавливать , и чем это грозит ...

Автор: Andrey44 9.10.2009, 07:03
Код

HANDLE hToken;
    TOKEN_PRIVILEGES* NewState;
    OpenProcessToken (GetCurrentProcess (), TOKEN_ADJUST_PRIVILEGES, &hToken);
    NewState = (TOKEN_PRIVILEGES*) malloc (sizeof(TOKEN_PRIVILEGES) + sizeof (LUID_AND_ATTRIBUTES));
    NewState->PrivilegeCount = 1;
    LookupPrivilegeValue (NULL, SE_MANAGE_VOLUME_NAME, &NewState->Privileges[0].Luid);
    NewState->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    AdjustTokenPrivileges (hToken, FALSE, NewState, NULL, NULL, NULL);
    free (NewState);
    CloseHandle (hToken);

Как-то так можно установить SE_MANAGE_VOLUME_NAME привелегии 
Ну а дальше пробуйте

Автор: hash_2000 9.10.2009, 07:06
ну ладно ... никому я смотрю не интересно ... или никто не знает ... 
для того чтобы установить привилегии для процесса нужно сделать следующее: 
Код


    TOKEN_PRIVILEGES tp;
    tp.PrivilegeCount = 1;
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    HANDLE hProc;
    if( !OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hProc ) )
    {

        if( LookupPrivilegeValue( NULL, SE_MANAGE_VOLUME_NAME, &tp.Privileges[0].Luid  ) )
            if( !AdjustTokenPrivileges( hProc, FALSE, &tp, 0, NULL, NULL ) )
                return ; // не получилось, выходим
    }

    HANDLE hFile = CreateFile( .... );

    SetFileValidData( hFile, 1 * 1024 * 1024 );
    DWORD dwerr = GetLastError();
    // вот здесь возникла новая ошибка dwerr == ERROR_INVALID_PARAMETER
    // проблема еще не решена



Добавлено через 1 минуту и 39 секунд
smile кто то написал вместе со мной ... только написали мы практически одно и тоже ... но сама проблема не решена

Автор: GremlinProg 9.10.2009, 08:49
SetFileValidData - это некоторый аналог разреженных файлов,
позволяет заполнить нулями некоторую файловую область, фзиически этого не делая

вот самые важные условия:
Цитата

Allocation size: the size of the space that is allocated for a file on a disk, which is always an even multiple of the cluster size
Valid data length: the length of the data in a file that is actually written, to the byte. This value is always less than or equal to the file size. 

Автор: hash_2000 9.10.2009, 10:22
... только вот функция почемуто постоянно возвращает ошибку ... 
хотя я нашел способ чтобы эта функция работала , перед ее вызовом нужно написать следующее:

Код


    LARGE_INTEGER pos;
    pos.QuadPart =  ... ; // тут размер указываем куда сдвинуться 

    pos.LowPart = SetFilePointer( m_hFile, 
        pos.LowPart, &pos.HighPart, (DWORD)FILE_BEGIN);

    // даже если файл меньшего размера чем указано в смещении функция всеравно возвращает истину
    // но при этом сам фал не станет указанного размера ..

    ::SetEndOfFile( m_hFile );
    // вот после этого и файл станет размером которое указано в смещении и уже после этого
    // можно вызывать SetFileValidData , как описано выше , функция будет возвращать истину ,
    // вот только не понятно зачем она тогда вообще нужна , если все что нужно было сделано ранее


Автор: GremlinProg 9.10.2009, 11:18
hash_2000, только SetEndOfFile и ставит физически размер файла, если он не разреженный
SetFilePointer этого делать и не должен

Автор: hash_2000 9.10.2009, 12:28
SetEndOfFile как получается не устанавливает физический размер файла , а устанавливает , так называемый логический размер файла ... тоесть на самом деле данных внутри файла нет ...
тоесть сначала мы ставим указатель в файле куданибудь с помощью функции SetFilePointer ... затем когда выполняем SetEndOfFile ... то по указателю в файле устанавливается размер ... 
я так понял работает эта функция ...
во первых если выполнить следующий код:

Код

 LARGE_INTEGER pos;
    pos.QuadPart =  0xFFFFFFFFF ; 
    pos.LowPart = SetFilePointer( m_hFile, 
        pos.LowPart, &pos.HighPart, (DWORD)FILE_BEGIN);
    ::SetEndOfFile( m_hFile );


... то функция слишком быстро выполнится , для выделения физического размера файла 64 ГБ
а если потом попробовать записать один байт в конец файла то сразу будет заметно что выделяется физическое пространство ...

Добавлено через 1 минуту и 22 секунды
вот теперь у меня вопрос в другом , зачем нужна функция SetFileValidData , если за нее все выполняет связка SetFilePointer и SetEndOfFile ... 

Автор: GremlinProg 9.10.2009, 12:43
Цитата(hash_2000 @  9.10.2009,  14:28 Найти цитируемый пост)
SetEndOfFile как получается не устанавливает физический размер файла , а устанавливает , так называемый логический размер файла


Цитата(SetEndOfFile Function @  MSDN)

Sets the physical file size for the specified file to the current position of the file pointer.


можешь поставить брейкпойнт после SetEndOfFile и посмотреть на сколько уменьшился объем диска
другое дело, сам диск - логическая единица, физически ставится только маркер в таблице файлов,
а заполнять файл нулями он не должен

Цитата(hash_2000 @  9.10.2009,  14:28 Найти цитируемый пост)
а если потом попробовать записать один байт в конец файла то сразу будет заметно что выделяется физическое пространство ...

это от физического размера не зависит,
тут начинает работать буферизация встроенная или своя - без разницы

Добавлено через 1 минуту и 58 секунд
Цитата(hash_2000 @  9.10.2009,  14:28 Найти цитируемый пост)
вот теперь у меня вопрос в другом , зачем нужна функция SetFileValidData , если за нее все выполняет связка SetFilePointer и SetEndOfFile

Цитата(GremlinProg @  9.10.2009,  10:49 Найти цитируемый пост)
позволяет заполнить нулями некоторую файловую область, фзиически этого не делая

т.е. при чтении данных после области, помеченной SetFileValidData, на самом деле буфера будут заполняться просто нулями, без обращения к диску

Автор: hash_2000 9.10.2009, 12:55
ну посмотрел я на сколько уменьшилось место на даске , после 

Код

LARGE_INTEGER pos;
    pos.QuadPart =  0xFFFFFFFFF ; 
    pos.LowPart = SetFilePointer( m_hFile, 
        pos.LowPart, &pos.HighPart, (DWORD)FILE_BEGIN);
    ::SetEndOfFile( m_hFile );


на 64 Гб уменьшилось ... и что это означает ? тоесть если я выполню SetFileValidData место на диске не уменьшится ... ? или я чегото не пойму ... 

Автор: GremlinProg 9.10.2009, 13:01
Цитата(hash_2000 @  9.10.2009,  14:55 Найти цитируемый пост)
если я выполню SetFileValidData место на диске не уменьшится ... ?

нет, не должно,
если ты поставишь его на 64 кб, то просто при последовательном чтении всего этого файла,
время чтения займет физическое чтение с диска 64кб + время заполнения оставшегося пространства нулями,
а это несоизмеримо меньше, чем если бы ты читал все 64 Гб

функция сделана специально "на вырост" файла, чтобы можно было заполнять его по факту наличия текущих данных,
а не по факту его конечного размера

Автор: hash_2000 9.10.2009, 13:05
ну тогда как заставить эту функцию работать ? выше я писал что получается без SetFilePointer и SetEndOfFile

Автор: GremlinProg 9.10.2009, 13:21
без SetFilePointer и SetEndOfFile функция будет работать только если ты откроешь заранее созданный файл достаточного размера, чтобы он покрывал размер, передаваемый в SetFileValidData

в остальных случаях SetFilePointer и SetEndOfFile обязательны

1. создай новый файл
2. сдвинь указатель на 64Гб
3. укажи конец файла
4. вызови SetFileValidData с размером в 64 кб

вот и все, можешь прочитать, к примеру в цикле этот файл с начала до конца буфером в 64 кб и посмотри насколько быстро это произойдет

потом можешь закомментировать SetFileValidData и снова запустить программу (для 64 Гб, пока она работает, ты успеешь и прогуляться, и поужинать и потом, скорее всего, когда тебе надоест ждать, ты просто ее "придушишь" )

Добавлено @ 13:28
кстати, когда будешь это делать, поставь брейкпойнт после вызова SetFileValidData и посмотри из эксплорера свойства файла, скажи есть ли разница между параметрами "Размер" и "На диске"

это будет точным ответом на твой вопрос: "место на диске не уменьшится ... ?"

Автор: hash_2000 9.10.2009, 14:02
GremlinProg попробовал я сделать так как ты написал , и с SetFileValidData  и без нее читает одинаково ... 
может я не правильно както написал , GremlinProg выложи код если не трудно ...  пример ...

Автор: GremlinProg 9.10.2009, 14:16
без проверок, примерно так:
Код

BYTE buffer[0x10000];
LARGE_INTEGER size;

hFile = ::CreateFile( lpszFilename, ... );
size.QuadPart= LONGLONG(64) * 1024 * 1024 * 1024;
::SetFilePointer( hFile, size.LowPart, &size.HighPart , FILE_BEGIN  );
::SetEndOfFile( hFile );
::SetFileValidData( 0x10000);
::SetFilePointer( hFile, 0, NULL, FILE_BEGIN  );

for( i =  size.QuadPart / sizeof(buffer) ; i-- ; ){
  ::ReadFile( hFile, buffer, 0x10000, &readed, NULL );
}

Автор: hash_2000 9.10.2009, 14:32
ну я все так и делал ... и место на диске отнялось и читает нифига не в мгновение ...
место отнялось после функции SetEndOfFile ... а после SetFileValidData ... оно если должно было прибавиться , то оно не прибавилось ... 
и читалось примерно одинаково по времени .... 

Автор: GremlinProg 9.10.2009, 14:56
Цитата(hash_2000 @  9.10.2009,  16:32 Найти цитируемый пост)
и читалось примерно одинаково по времени

значит бонус только в том, что не приходится писать нули в файл,

хотя и нелогично, физически он же их не пишет

может стоит перед чтением его заполнить:
Код

for( i =  sizeof(buffer) ; i-- ; ){
  buffer[i] = (BYTE)i;
}
::SetFilePointer( hFile, 0, NULL, FILE_BEGIN  );
for( i =  size.QuadPart / sizeof(buffer) ; i-- ; ){
  ::WriteFile( hFile, buffer, sizeof(buffer), &wr, NULL );
}
::SetFilePointer( hFile, 0, NULL, FILE_BEGIN  );
::SetFileValidData( 0x10000);
for( i =  size.QuadPart / sizeof(buffer) ; i-- ; ){
  ::ReadFile( hFile, buffer, sizeof(buffer), &readed, NULL );
}

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)