Консультация № 187617
11.11.2013, 21:03
134.08 руб.
0 21 1
Здравствуйте, уважаемые эксперты!
Ситуация такая, опираясь на статью http://www.manhunter.ru/software/588_kak_razbit_fleshku_na_neskolko_razdelov.html разбил свою флешку на 2 раздела: активный и скрытый.
Есть утилита под Linux, gparted, у которой есть возможность отключать и включать разделы на дисках ставя галочку на против пункта hidden. Эта утилита позволяет заблокировать раздел на диске и никакая система (штатными средствами) не может получить к ней доступ. Вопрос такой, как это реализовать средствами Visual Studia C++ для Windows? Мне нужно включать и отключать "Скрытый" раздел

Полагаю, что для этого нужно вносить изменения в MBR. Нашел код на Visual C++, который собирает информацию о MBR

Код:
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>

#pragma pack(push, 1)
typedef struct PART
{
BYTE ActFlag;
BYTE Begin_Hd;
WORD Begin_SecTrk;
BYTE SysCode;
BYTE End_Hd;
WORD End_SecTrk;
DWORD RelSec;
DWORD Size;
};

typedef struct MBR
{
BYTE LoadCode[0x1BE];
struct PART rt[4];
WORD EndFlag;
};
#pragma pack(pop)

int main(void)
{
HANDLE hDrive = CreateFile(L"\\\\.\\PhysicalDrive1",
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if (INVALID_HANDLE_VALUE == hDrive)
fprintf(stderr, "CreateFile failed 0x%08X\n", GetLastError());
else
{
struct MBR mbr;
DWORD NumberOfBytesRead = 0;

RtlZeroMemory(&mbr, sizeof(mbr));
if (0 == ReadFile(hDrive, &mbr, sizeof(mbr), &NumberOfBytesRead, 0))
fprintf(stderr, "ReadFile failed 0x%08X\n", GetLastError());
else if (sizeof(mbr) != NumberOfBytesRead)
fprintf(stderr, "sizeof(mbr) = 0x%08X, ReadFile read 0x%08X\n",
sizeof(mbr), NumberOfBytesRead);
else
{
int j;

for (j = 0; j < 4; j++)
fprintf(stdout, "Partition %d\n"
" ActFlag = 0x%02X\n"
" Begin_Hd = 0x%02X\n"
" Begin_SecTrk = 0x%04X\n"
" SysCode = 0x%02X\n"
" End_Hd = 0x%02X\n"
" End_SecTrk = 0x%04X\n"
" RelSec = 0x%08X\n"
" Size = 0x%08X\n\n",
j,
mbr.rt[j].ActFlag,
mbr.rt[j].Begin_Hd,
mbr.rt[j].Begin_SecTrk,
mbr.rt[j].SysCode,
mbr.rt[j].End_Hd,
mbr.rt[j].End_SecTrk,
mbr.rt[j].RelSec,
mbr.rt[j].Size);
}

CloseHandle(hDrive);
}

system("pause");
return 0;
}


Когда я блокирую и разблокировываю раздел на диске, меняется значения SysCode на 6 и на 16.

Обсуждение

Неизвестный
12.11.2013, 09:06
общий
Вы правильно полагаете, для этой задачи нужно модифицировать поле PartitionType (оно же SysCode) соответсвующей записи в таблице разделов MBR (или расширенной таблице в общем случае). Конкретные значения должны быть согласованы с типом файловой системы скрытого раздела, см http://en.wikipedia.org/wiki/Partition_type.
После изменения таблицы разделов нужно уведомить систему. Например, с помощью запроса IOCTL_DISK_UPDATE_PROPERTIES. На первых порах можно использовать кнопку Rescan в панели Disk Management.
При скрытии раздела желательно его заблокировать с помощью FSCTL_LOCK_VOLUME, чтобы убедиться в отсутствии открытых файлов и исключить потерю несохранённых данных пользователя.
Неизвестный
12.11.2013, 22:03
общий
Из-за разное расположение PartitionType, в зависимости от файловой системы и фирмы, утилита gparted не всегда может отключить раздел? Раздел с NTFS та утилита может отключить.

Цитата: 321399
После изменения таблицы разделов нужно уведомить систему. Например, с помощью запроса IOCTL_DISK_UPDATE_PROPERTIES. На первых порах можно использовать кнопку Rescan в панели Disk Management.
При скрытии раздела желательно его заблокировать с помощью FSCTL_LOCK_VOLUME, чтобы убедиться в отсутствии открытых файлов и исключить потерю несохранённых данных пользователя.


Т.е. получается, что надо
1) попытаться заблокировать раздел с помощью FSCTL_LOCK_VOLUME, если не получается, то отменяем все шаги
2) модифицируем запись в PartitionType
3) уведомляем систему с помощью IOCTL_DISK_UPDATE_PROPERTIES
Правильно?

1) FSCTL_LOCK_VOLUME Не понятно пока одно, вроде код выполняется нормально, но флешка как работала, так и работает, даже открытый на ней музыкальный файл не мешает вывести сообщение "Диск заблокирован"

Код:
#include "stdafx.h"
#include <windows.h>

int main(int argc, char* argv[])
{
HANDLE hDevice;
DWORD lpBytesReturned;

hDevice = CreateFile(L"\\\\.\\PhysicalDrive1", // это мой флэш накопитель
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
0,
OPEN_EXISTING,
0,
0);
if (INVALID_HANDLE_VALUE == hDevice)
{
char buf[64];
CharToOem(L"Флешка не вставлена\n", buf);
printf(buf);
}
if (DeviceIoControl(hDevice,
FSCTL_LOCK_VOLUME,
NULL, 0,
NULL, 0,
&lpBytesReturned,
NULL))
{
char buf[64];
CharToOem(L"Диск заблокирован\n", buf);
printf(buf);
}
system("pause");
}


2) Про PartitionType пока не понятно вообще. Все еще остается вопросом

3) IOCTL_DISK_UPDATE_PROPERTIES вроде бы вот код, но проверить его работу пока не могу

Код:
DeviceIoControl(hDevice, IOCTL_DISK_UPDATE_PROPERTIES,
NULL,0,NULL,0,&lpBytesReturned,NULL);
Неизвестный
12.11.2013, 23:09
общий
Общая схема верная.

1) FSCTL_LOCK_VOLUME надо посылать на том, в вашем примере он посылается на диск. То есть вместо "PhysicalDriveX" надо открывать "X:"

2) PartitionType всегда находится по одному смещению в MBR, но значения зависят от типа файловой системы: для FAT16 - x06 и x16, для FAT32 - 0x0B и 0x1B, и так далее по таблице в википедии.
Неизвестный
12.11.2013, 23:48
общий
С 1м теперь понятно. Не блокирует, но проверяет. Если что-то запустить, то не выводит ничего кроме от system("pause");

Со 2м. Если пока ограничиться FAT16, то как мне там изменять значения?
Неизвестный
13.11.2013, 09:16
общий
Если FAT16, то для скрытия раздела надо заменить PartitionType cо значения 6h на 16h. Чтобы сделать видимым - наоборот.
Заменять значения так:
1) Прочитать первые 512 байт с диска, как в исходном примере
2) Убедиться, что байт со смещением 1BEh + x*10h + 4h имеет ожидаемое значение (т.е. 6 или 16h)
3) Заменить в буфере значение
4) Записать получившиеся 512 байт на диск по нулевому смещению
Неизвестный
13.11.2013, 20:48
общий
13.11.2013, 22:46
Что тут не так? Я исключил проверки, а только чтение, изменение и запись. Ошибок нет, но не записывает

Код:

...
int main(void)
{
HANDLE hDrive = CreateFile(L"\\\\.\\PhysicalDrive1",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if (INVALID_HANDLE_VALUE == hDrive)
fprintf(stderr, "CreateFile failed 0x%08X\n", GetLastError());
else
{
struct MBR mbr;
DWORD NumberOfBytesRead = 0;
RtlZeroMemory(&mbr, sizeof(mbr));
ReadFile(hDrive, &mbr, sizeof(mbr), &NumberOfBytesRead, 0);

printf("Partition %d\n SysCode = 0x%02X\n",1,mbr.rt[1].SysCode);

switch(mbr.rt[1].SysCode)
{
case 6: mbr.rt[1].SysCode=22; break; //FAT16 скрываем
case 22: mbr.rt[1].SysCode=6; break; //FAT16 открываем
case 11: mbr.rt[1].SysCode=27; break;//FAT32 скрываем
case 27: mbr.rt[1].SysCode=11; break;//FAT32 открываем
default:break;
}

WriteFile(hDrive, &mbr, sizeof(mbr), &NumberOfBytesRead, 0);
CloseHandle(hDrive);
}
system("pause");
return 0;
}


Верх программы, где ... - такой же как в начале.
WriteFile(hDrive, &mbr, sizeof(mbr), &NumberOfBytesRead, 0); возвращает true, но результата нет. Отладчиком прошелся по mbr и увидел что значения не изменились почему-то
Неизвестный
13.11.2013, 21:00
общий
Срок вопроса поджимает, а я пока его так и не довел до конца...
Код:
Состояние: Консультация активна (до закрытия: 1 сут. 00 час. 06 мин.)
давно
Старший Модератор
31795
6196
13.11.2013, 22:59
общий
13.11.2013, 23:03
Тут смотрели?
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Старший Модератор
31795
6196
13.11.2013, 23:06
общий
Цитата: 396816
Срок вопроса поджимает,

Алёна(Администратор Рассылки) - продлила Ваш вопрос, даже после окончания срока действия- сам мини-форум вопроса будет активен.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
13.11.2013, 23:18
общий
Спасибо! Вникнуть бы чем это может помочь с MBR
Неизвестный
14.11.2013, 10:00
общий
В последнем примере запись происходит в 1-й сектор диска, а нужно писать в нулевой. Используйте фукнцию SetFilePointerEx перед записью:
LARGE_INTEGER position = {0};
if (!SetFilePointerEx(hDrive, position, 0, FILE_BEGIN))
{
// обработка ошибки
}
WriteFile(...)
давно
Старший Модератор
31795
6196
14.11.2013, 11:30
общий
Цитата: 396816
Спасибо! Вникнуть бы чем это может помочь с MBR

Диск открывается как файл.
Как только Вы прочитали сектор(512 байт), то указатель в файле(на диске) переместился на следующий сектор.
Цитата: 321399
В последнем примере запись происходит в 1-й сектор диска, а нужно писать в нулевой.

Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
14.11.2013, 22:47
общий
14.11.2013, 22:54
Пока плаваю

[code h=200]#include "stdafx.h"
#include <windows.h>
#include <stdio.h>

HANDLE hD;

bool DiskOpen(char *vol)
{
char szDrive[10];
// sprintf(szDrive, L"\\\\.\\%c:", vol[0]);
hD = CreateFile(
// szDrive,
L"\\\\.\\PhysicalDrive1",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
return hD != INVALID_HANDLE_VALUE;
}

void DiskClose()
{
if (hD != INVALID_HANDLE_VALUE)
CloseHandle(hD);
}

bool ReadSector (DWORD sector, char *Buffer, int sectorSize)
{
DWORD read = 0;
if (SetFilePointer(hD, sector, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
return false;

if (!ReadFile(hD, Buffer, sectorSize, &read, NULL))
return false;

return true;
}


bool WriteSector(DWORD sector, char *Buffer, int sectorSize)
{
DWORD wrote = 0;
LARGE_INTEGER position = {0};
if (!SetFilePointerEx(hD, position, 0, FILE_BEGIN))
{
return false;
}

if (!WriteFile(hD, Buffer, sectorSize, &wrote, NULL))
return false;

return true;
}

void main()
{
DWORD OpenClose = 6;
const int max_pbsi = 3;
//определяем структуру для сигнатуры загрузочной области
struct partial_boot_sector_info
{
LPSTR Fs; // название файловой системы
DWORD FsOffs; // partition
DWORD SerialOffs; // смещение
};
//описываем часто используемые сигнатуры
partial_boot_sector_info pbsi[max_pbsi] =
{
{"FAT32", 0x1BE, 0x10}, //Пока испытываю на флешке с одним разделом
{"FAT", 0x1BE, 0x10},
{"NTFS", 0x1BE, 0x10}
};
//инициализируем необходимые переменные
char Drive[12]={0};
char Sector[512];
DWORD i;
sprintf(Drive, "\\\\.\\PhysicalDrive1");
//открываем диск
if (!DiskOpen(Drive))
{//если ошибка оповещаем пользователя и выходим из процелуры
char buf[64];
CharToOem(L"Ошибка\nНевозможно открыть диск!", buf);
printf(buf);
return;
}
// читаем загрузочную область
if (!ReadSector(0, Sector,512))
{
char buf[64];
CharToOem(L"Ошибка\nНевозможно считать данные", buf);
printf(buf);
return;
}

// поиск сигнатуры загрузочной области
for (i=0;i==max_pbsi,i++;)
{
char buf[64];
CharToOem(L"Ошибка\nНевозможно сменить номер для этой файловой системы!", buf);
printf(buf);
return;
}

// меняем номер
*(PDWORD)(Sector+pbsi[i].SerialOffs) = OpenClose;

// записываем в загрузочную область
if (!WriteSector(0, Sector,512))
{
char buf[64];
CharToOem(L"Ошибка\nНевозможно записать на диск!", buf);
printf(buf);
return;
}
DiskClose();
char buf[64];
CharToOem(L"Внимание!\nСерийный номер успешно изменен! Необходимо перезагрзить компьютер.", buf);
printf(buf);

printf("\n");
system("pause");
}[/code]
давно
Старший Модератор
31795
6196
14.11.2013, 22:59
общий
Возмите две функции ReadSector и WriteSector, в main определите переменную MBR = 0 и передавайте её как адрес сектора в эти функции. Всё.
Вы всегда будете читать и писать одну и туже информацию по одному адресу.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

давно
Старший Модератор
31795
6196
14.11.2013, 23:16
общий
Приблизительно так:
Код:
int main(void)
{
HANDLE hDrive = CreateFile(L"\\\\.\\PhysicalDrive1",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if (INVALID_HANDLE_VALUE == hDrive)
fprintf(stderr, "CreateFile failed 0x%08X\n", GetLastError());
else
{
struct MBR mbr;
DWORD NumberOfBytesRead = 0;
RtlZeroMemory(&mbr, sizeof(mbr));
ReadSector(....);

printf("Partition %d\n SysCode = 0x%02X\n",1,mbr.rt[1].SysCode);

switch(mbr.rt[1].SysCode)
{
case 6: mbr.rt[1].SysCode=22; break; //FAT16 скрываем
case 22: mbr.rt[1].SysCode=6; break; //FAT16 открываем
case 11: mbr.rt[1].SysCode=27; break;//FAT32 скрываем
case 27: mbr.rt[1].SysCode=11; break;//FAT32 открываем
default:break;
}

WriteSector(....);
CloseHandle(hDrive);
}
system("pause");
return 0;
}
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
15.11.2013, 00:58
общий
Да, работает. Диск скрывается

Код:
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>

HANDLE hD;

#pragma pack(push, 1)
struct PART
{
BYTE ActFlag;
BYTE Begin_Hd;
WORD Begin_SecTrk;
BYTE SysCode;
BYTE End_Hd;
WORD End_SecTrk;
DWORD RelSec;
DWORD Size;
};
struct MBR
{
BYTE LoadCode[0x1BE];
struct PART rt[4];
WORD EndFlag;
};
#pragma pack(pop)

bool ReadSector (DWORD sector, MBR *mbr, int sectorSize)
{
DWORD read = 0;
if (SetFilePointer(hD, sector, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
return false;

if (!ReadFile(hD, mbr, sectorSize, &read, NULL))
return false;

return true;
}


bool WriteSector(DWORD sector, MBR *mbr, int sectorSize)
{
DWORD wrote = 0;
LARGE_INTEGER position = {0};
if (!SetFilePointerEx(hD, position, 0, FILE_BEGIN))
{
return false;
}

if (!WriteFile(hD, mbr, sectorSize, &wrote, NULL))
return false;

return true;
}

int main(void)
{
hD = CreateFile(L"\\\\.\\PhysicalDrive1",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if (INVALID_HANDLE_VALUE == hD)
fprintf(stderr, "CreateFile failed 0x%08X\n", GetLastError());
else
{
struct MBR mbr;
DWORD NumberOfBytesRead = 0;
RtlZeroMemory(&mbr, sizeof(mbr));
ReadSector(0,&mbr,512);
printf("Partition %d\n SysCode = 0x%02X\n",1,mbr.rt[1].SysCode);
switch(mbr.rt[1].SysCode)
{
case 6: mbr.rt[1].SysCode=22; break; //FAT16 скрываем
case 22: mbr.rt[1].SysCode=6; break; //FAT16 открываем
case 11: mbr.rt[1].SysCode=27; break;//FAT32 скрываем
case 27: mbr.rt[1].SysCode=11; break;//FAT32 открываем
default:break;
}
WriteSector(0,&mbr,512);
CloseHandle(hD);
}
system("pause");
return 0;
}


Спасибо!

Теперь я соберу как полагается
Цитата: 396816

1) попытаться заблокировать раздел с помощью FSCTL_LOCK_VOLUME, если не получается, то отменяем все шаги
2) модифицируем запись в PartitionType
3) уведомляем систему с помощью IOCTL_DISK_UPDATE_PROPERTIES


Хочу проверить работу 3 пункта и работу целиком программы

Еще вопросик возник, вот как сделать переносную консольную программу, собранную в Win32? На компьютере где этот код должен выполняться не установлен язык программирования. При создании проекта с консольным приложением под Win32 нет галочки статической сборки.
Собираю на ОС Windows XP, пытаюсь открыть на Windows Seven
Неизвестный
15.11.2013, 08:53
общий
Ошибка выскакивает потому что программа использует динамическую C RunTime библиотеку. А на компьютере эта версия CRT не установлена.
В свойствах проекта Visual Studio есть настройка С++/Code Generation/Runtime Library. Чтобы использовать статический Runtime нужно поменять её с "Multi-threaded DLL" на "Multi-threaded".
давно
Старший Модератор
31795
6196
15.11.2013, 15:04
общий
15.11.2013, 16:04
Цитата: 396816
Еще вопросик возник, вот как сделать переносную консольную программу, собранную в Win32?

Тогда Вам без асма не обойтись, т.к. переносимость зависит от всего, что ОСи подгружают. А тут чистый BIOS.

Компилятор Тасм будет работать на всех х86++ процессорах.
Код:
model	tiny
xorData equ 10h
.code
org 100h
begin:
;читаем сектор
mov ax,0201h
call RWSector
;читаем SysCode и анализипуем его
mov al,SysCode
cmp al,06h;06
jz isJob
cmp al,16h;22
jz isJob
cmp al,0Bh;11
jz isJob
cmp al,1Bh;27
jnz isSkeep
;меняем переключаем значение скрытый
isJob: xor al,xorData
;записываем SysCode
isSkeep: mov SysCode,al
;пишем сектор
mov ax,0301h
call RWSector
;возврат в ОС
ret
;подпрограмма чтения-записи сектора
RWSector: mov cx,0001h
mov dx,0000h;младший байт определяет дисковод
lea bx,dbBuffer
int 13h
ret
;буфер обмена
dbBuffer db 446 dup(?);
;первое поле описания диска
db 16 dup(?);mbr.rt[0]
;поле описания диска mbr.rt[1]
db ?;ActFlag
db ?;Begin_Hd
dw ?;Begin_SecTrk
SysCode db ?;
db ?;End_Hd
dw ?;End_SecTrk
dd ?;RelSec
dd ?;Size
;остальные поля описания mbr.rt[2 & 3]
db 2*16 dup(?)
;сигнатура
db ?,?;
end begin


mov dx,00[u]00[/u]h; - c выделенным байтом Вам нужно будет поработать, для поиска кода флешки.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
15.11.2013, 23:05
общий
16.11.2013, 00:37
Все, работает как надо Спасибо! )
Вопрос уже решен. Любопытно только вот что, выше приведен код ассемблера. Можно ли его включить в оператор _asm ? и как? Интересно просто?
Ниже рабочий код моей программы

[code h=200]
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>

HANDLE hD;

#pragma pack(push, 1)
struct PART
{
BYTE ActFlag;
BYTE Begin_Hd;
WORD Begin_SecTrk;
BYTE SysCode;
BYTE End_Hd;
WORD End_SecTrk;
DWORD RelSec;
DWORD Size;
};
struct MBR
{
BYTE LoadCode[0x1BE];
struct PART rt[4];
WORD EndFlag;
};
#pragma pack(pop)

bool ReadSector (DWORD sector, MBR *mbr, int sectorSize)
{
DWORD read = 0;
if (SetFilePointer(hD, sector, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
return false;

if (!ReadFile(hD, mbr, sectorSize, &read, NULL))
return false;

return true;
}


bool WriteSector(DWORD sector, MBR *mbr, int sectorSize)
{
DWORD wrote = 0;
LARGE_INTEGER position = {0};
if (!SetFilePointerEx(hD, position, 0, FILE_BEGIN))
{
return false;
}

if (!WriteFile(hD, mbr, sectorSize, &wrote, NULL))
return false;

return true;
}

bool check()
{
HANDLE hDevice;
DWORD lpBytesReturned;
hDevice = CreateFile(L"\\\\.\\E:", // это мой флэш накопитель
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
0,
OPEN_EXISTING,
0,
0);
if (INVALID_HANDLE_VALUE == hDevice)
{
char buf[64];
CharToOem(L"Флешка не вставлена\n", buf);
printf(buf);
CloseHandle(hDevice);
return false;
}
if (!DeviceIoControl(hDevice,
FSCTL_LOCK_VOLUME,
NULL, 0,
NULL, 0,
&lpBytesReturned,
NULL))
{
char buf[64];
CharToOem(L"Диск заблокирован\n", buf);
printf(buf);
CloseHandle(hDevice);
return false;
}
CloseHandle(hDevice);
return true;
}

void rMBR()
{
hD = CreateFile(L"\\\\.\\PhysicalDrive1",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if (INVALID_HANDLE_VALUE == hD)
fprintf(stderr, "CreateFile failed 0x%08X\n", GetLastError());
else
{
struct MBR mbr;
DWORD NumberOfBytesRead = 0;
RtlZeroMemory(&mbr, sizeof(mbr));
if(ReadSector(0,&mbr,512))
{
printf("Partition %d\n SysCode = 0x%02X\n",1,mbr.rt[1].SysCode);
switch(mbr.rt[1].SysCode)
{
case 6: mbr.rt[1].SysCode=22; break; //FAT16 скрываем
case 22: mbr.rt[1].SysCode=6; break; //FAT16 открываем
case 11: mbr.rt[1].SysCode=27; break;//FAT32 скрываем
case 27: mbr.rt[1].SysCode=11; break;//FAT32 открываем
default:break;
}
if(!WriteSector(0,&mbr,512)) printf("Error\n");
else printf("Partition %d\n SysCode = 0x%02X\n",1,mbr.rt[1].SysCode);
}
}
}

void refresh()
{
DWORD lpBytesReturned;
DeviceIoControl(hD, IOCTL_DISK_UPDATE_PROPERTIES,
NULL,0,NULL,0,&lpBytesReturned,NULL);
}


void main()
{
if(check())
{
rMBR();
refresh();
}
else
{
char buf[64];
CharToOem(L"Ошибка\n", buf);
printf(buf);
}
CloseHandle(hD);
system("pause");
}
[/code]
давно
Старший Модератор
31795
6196
16.11.2013, 01:18
общий
18.11.2013, 14:02
Вставить асм-код в С просто. Все структурные компиляторы высокого уровня позволяют делать вставки на языке ассемблер(правда нужно очень хорошо выучить различного рода соглашения, а так это не проблема). Проблема заключается только в том, что сами компиляторы навешивают на код ассемблера( в данном случае 516 байт) ещё и так называемые "прологи" и "эпилоги", т.е. код называемый "болваном". Он принимает управление от системы, устанавливает свои обработчики ошибок , и по окончанию всё возвращает в исходное состояние. Этот код меняется от версии компиляторов и мешает переносить скомпилированную программу на разные системы.

Вашу программу можно сделать более переносимой, если использовать чистое WIN API, т.е. исключить стандартные библиолтеки компиляторов. Как пример функция SetFilePointer как была в Kernel32.dll, так там и осталась и будет работать начиная с Windows 95 и заканчивая Windows XP(WIn 8 нужно смотреть код библиотеки). Для простых программ достаточно только библиотек USER, KERNEL и GDI. Все функции практически повторяются от системы к системе.
Об авторе:
Мне безразлично, что Вы думаете о обо мне, но я рад за Вас - Вы начали думать.

Неизвестный
19.11.2013, 11:49
общий
это ответ
Здравствуйте, Игорь!

Вы правильно полагаете, для этой задачи нужно модифицировать поле PartitionType (оно же SysCode) соответсвующей записи в таблице разделов MBR (или расширенной таблице в общем случае). Конкретные значения должны быть согласованы с типом файловой системы скрытого раздела, см http://en.wikipedia.org/wiki/Partition_type.
После изменения таблицы разделов нужно уведомить систему. Например, с помощью запроса IOCTL_DISK_UPDATE_PROPERTIES. На первых порах можно использовать кнопку Rescan в панели Disk Management.
При скрытии раздела желательно его заблокировать с помощью FSCTL_LOCK_VOLUME, чтобы убедиться в отсутствии открытых файлов и исключить потерю несохранённых данных пользователя.

Общая схема действий такова:

1) Попытаться заблокировать раздел с помощью FSCTL_LOCK_VOLUME, если не получается, то отменяем все шаги.
Для посылки этого запроса надо открыть том по имени вида "\\.\X:"

2) Модифицикация поля PartitionType в MBR, соответствующего разделу.
Заменять значения так:
- Прочитать первые 512 байт с диска, как в исходном примере
- Убедиться, что байт со смещением 1BEh + x*10h + 4h имеет ожидаемое значение (т.е. 6 или 16h для FAT16)
- Заменить в буфере значение
- Записать получившиеся 512 байт на диск по нулевому смещению
Для работы с диском на блочном уровне целесообразно завести две функци ReadSector и WriteSector.
Перед выполнением операций не забыть установить текущую позицию на нужный сектор с помощью SetFilePointerEx

3) Уведомляем систему с помощью IOCTL_DISK_UPDATE_PROPERTIES

Удачи!
Форма ответа