For some weird reason, using XP Embedded (same APIs & binaries as XP
Pro), after updating a partition with a tool, we end up making an other
perfectly valid NTFS partition invisible. All I need to do is use some
3rd party utility to make the partition visible again, but that's not an
option in the field: I need to check for that condition and fix it.
I'm partitialy there: I can detect the condition using DeviceIoControl &
IOCTL_DISK_GET_DRIVE_LAYOUT_EX. I'll find the hidden partition, and
recognize it is hidden because of its type (PARTITION_IFS + 0x10), as
described here: http://boot-us.com/gloss08.htm
I have been able to use IOCTL_DISK_SET_DRIVE_LAYOUT_EX after changing
the partition type to PARTITION_IFS, but that doesn't stick, although
the API call doesn't return any error code. The partition remains
invisible, and the next time the code is run, it will see it again as an
invisible partition.
Does anyone have a suggestion?
Thanks in advance!
-georges
In addition to changing the partition type, I hope you also set the RewritePartition flag to TRUE. This will ensure that the changes to that partition entry are written out to disk
--
karan
--
This posting is provided "AS IS" with no warranties, and confers no rights.
Many thanks for your help!
No, I wasn't, and that solves the problem. Well, at least a great deal
of it: The change takes now, and after rebooting, the partition is
indeed visible.
The MSDN documentation is rather misleading for the use of that field:
"RewritePartition
If this member is TRUE, the partition is rewritable. The value of this
parameter should be set to TRUE." in the "PARTITION_INFORMATION_EX"
page. The real behavior can be found in the page "PARTITION_INFORMATION"
page though...
So now, I'd like to make the partition visible immediately.
I tried to call:
DWORD count;
DeviceIoControl(disk, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0,
&count, NULL);
(if you use the MSDN version telling you that you may pass 0 in place of
&count, it'll crash...).
...but that doesn't work. If I re-run my code that reads the partition
layout, I can see that the partition type has indeed been changed, but
the volume won't be mounted. Any suggestion?
thanks!
-georges
I need this behavior. Could you tell me is this real hiding like EWF does.
I'm trying to make my RAW data partition hidden in way EWF partition is
hidden, so even Disk Management can't see it.
Is this how your partition behaves, or you can see it from DM.
I really need this answer, because I don't want to lose time trying to do
this, and then to accomplish nothing.
Best regards,
Slobodan
Before anybody else gets confused, I'd precise that we are talking about
XP Embedded.
I don't know how EWF hides its partitions (I don't use EWF, so I can't
easily investigate that).
My case was "simply" that some partition recovery tool we are evaluating
was hidding all other partitions when making a partition active. That's
brain dead IMO. They claim it's a feature because of DOS/Win 9x legacy
issues. In my case, I just want to make the first primary NTFS partition
active, and the second NTFS partition is made hidden as a side effect...
I'd use some disk partitionning tool that let you see partition types.
It might tell you what partition type EWF uses.
-georges
Yes we are talking about XP Embedded.
But I have same behavior with XP and EWF partition, as expected.
I'm interested in your side effect.
When you enter Disk Management do you see this hidden partition? Because
when EWF create partition, it is hidden in Disk Management.
While doing preliminary testing I have read programmatically id of EWF
partition. But I don't think that it is a good idea to use that id because I
need EWF disk protection.
So there must be a way of making partition completely hidden for all MS
utilities.
I'm guessing that MS has some reserved values for future partitions, or
there is a standard way of hiding partitions completely.
I have looked at the link you mentioned in this thread. But they say to add
0x10 to partition id, and make it RAW.
But also say:
Comment:
It is possible that Windows 2000/XP/2003 considers a true hidden partition
as unformatted. This can be changed by removing the drive letter from a true
hidden partition. This prevents that you accidentally format such an
"unformatted" partition thereby deleting all existing data on that
partition. Drive letters are assigned resp. removed within the Windows disk
administrator (Computer Management / Storage / Disk Management).
This is thing I need to avoid, It *must be invisible*.
So I only wanted to know can you see this partition from Disk Management?
Or better if there is a way of doing this programmatically.
Best regards,
Slobodan
Yes, you can see this partition from the Disk Management tool, so this
type of partition hidding doesn't do what you want.
Oddly enough, the partition appears as "Healthy (Unknown partition)",
and the only option I am given it to delete the partition.
> Or better if there is a way of doing this programmatically.
My guess is that the Disk Management tool knows about some particular
partition types it should keep hidden. But this is pure speculation.
You can use free tools such as "MBRWork" (you can find it here:
http://www.terabyteunlimited.com/utilities.html) to see what type EWF
uses for its hidden partition. Then you can try to make a regular test
partition (FAT32 or NTFS) and change its type to the type you found
earlier, and see if that partition appears in mbrwork.
If that works, then yes, you can do this type changing operation
programmaticaly.
You can also use the code below to find out what partitions are in your
system. Works only with XP:
struct BIG_DRIVE_LAYOUT_INFORMATION_EX {
DWORD PartitionStyle;
DWORD PartitionCount;
union {
DRIVE_LAYOUT_INFORMATION_MBR Mbr;
DRIVE_LAYOUT_INFORMATION_GPT Gpt;
};
PARTITION_INFORMATION_EX PartitionEntry[100];
};
BIG_DRIVE_LAYOUT_INFORMATION_EX layout;
::memset(&layout, 0, sizeof(layout));
DWORD words;
BOOL result = DeviceIoControl(disk,
IOCTL_DISK_GET_DRIVE_LAYOUT_EX,
NULL, 0, // no input buffer
&layout, sizeof(layout), // output buffer
&words, // # bytes returned
NULL); // synchronous I/O
if (result == 0)
{
// error
}
else
{
int count = 0;
int hiddenCount = 0;
for (int p = 0; p < layout.PartitionCount; p++)
{
PARTITION_INFORMATION_EX & part = layout.PartitionEntry[p];
if (part.PartitionStyle == PARTITION_STYLE_MBR)
{
PARTITION_INFORMATION_MBR & mbr = part.Mbr;
if (mbr.RecognizedPartition)
{
count++;
printf("Partition %d: Start: 0x%016I64X Length: 0x%016I64X\n",
part.PartitionNumber, part.StartingOffset, part.PartitionLength);
Cmn_String type;
switch (mbr.PartitionType)
{
case PARTITION_ENTRY_UNUSED: type = "unused"; break;
case PARTITION_FAT_12: type = "FAT 12"; break;
case PARTITION_FAT_12 + 0x10: type = "FAT 12 Hidden"; break;
case PARTITION_XENIX_1: type = "Xenix 1"; break;
case PARTITION_XENIX_2: type = "Xenix 2"; break;
case PARTITION_FAT_16: type = "FAT 16"; break;
case PARTITION_FAT_16 + 0x10: type = "FAT 12"; break;
case PARTITION_EXTENDED: type = "Extended"; break;
case PARTITION_HUGE: type = "Huge"; break;
case PARTITION_HUGE + 0x10: type = "Huge Hidden"; break;
case PARTITION_IFS: type = "NTFS"; break;
case PARTITION_IFS + 0x10: type = "NTFS Hidden"; break;
case PARTITION_OS2BOOTMGR: type = "OS2 Boot Manager"; break;
case PARTITION_FAT32: type = "FAT 32"; break;
case PARTITION_FAT32 + 0x10: type = "FAT 32 Hidden"; break;
case PARTITION_FAT32_XINT13: type = "FAT 32 Int13"; break;
case PARTITION_FAT32_XINT13 + 0x10: type = "FAT 32 Int13 Hidden";
break;
case PARTITION_XINT13: type = "Int13"; break;
case PARTITION_XINT13 + 0x10: type = "Int13 Hidden"; break;
case PARTITION_XINT13_EXTENDED: type = "Int13 Extended"; break;
case PARTITION_XINT13_EXTENDED + 0x10: type = "Int13 Extended
Hidden"; break;
case PARTITION_PREP: type = "Prep"; break;
case PARTITION_LDM: type = "LDM"; break;
case PARTITION_UNIX: type = "Unix"; break;
default: type.Printf("0x%02X", mbr.PartitionType);
}
printf("Type: %s %s %s\n", type, (mbr.BootIndicator? "Boot" : ""),
(mbr.RecognizedPartition ? "" : "Not recognized"));
}
}
else
{
printf("Partition %d isn't an MBR partition.\n", p);
}
}
}
::CloseHandle(disk);
Cheers,
georges
> Yes, you can see this partition from the Disk Management tool, so this
> type of partition hidding doesn't do what you want.
> Oddly enough, the partition appears as "Healthy (Unknown partition)",
> and the only option I am given it to delete the partition.
This is info I wanted to know.
As long as user must first delete partition it should be ok, even if I don't
make it invisible.
I have already written part for reading partition id's. But nevertheless
thanks for you time.
Best regards,
Slobodan
Georges Berenger wrote:
--
Nick Ryan (MVP for DDK)
Good thinking.
But I'll try to avoid this, if possible.
Thanks,
Slobodan
I shall get the documentation corrected. Thank you for pointing this out
| So now, I'd like to make the partition visible immediately.
| I tried to call:
| DWORD count;
| DeviceIoControl(disk, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0,
| &count, NULL);
| (if you use the MSDN version telling you that you may pass 0 in place of
| &count, it'll crash...).
| ...but that doesn't work. If I re-run my code that reads the partition
| layout, I can see that the partition type has indeed been changed, but
| the volume won't be mounted. Any suggestion?
|
Currently, the volume manager isn't notified when the partition type changes and hence doesn't "unhide" the volume. To work around this, try the following -
1. Change the partition type to PARTITION_ENTRY_UNUSED but without setting the RewritePartition flag. This will cause the partition and hence the volume node to disappear but without committing the change to disk
2. Change the partition type to PARTITION_IFS with the RewritePartition flag set to TRUE. This will cause a new volume node to be created and exposed to the system, at the same time persisting this setting on disk
:)
Thanks for the suggestion. This time, it didn't work. The disk remains
unvisible, and I still have to reboot to see the partition.
This *might* be due to the fact that I am using my own XP Embedded
image, and that some component may be missing to get the expected
behavior? In which case, do you have any idea which component could be
involved?
-georges
Ack... just noticed that the RewritePartition flag cannot be used in this manner. Sorry about that - could you try the following instead -
1. Read in the layout and save away the contents of the partition entry corresponding to the hidden partition
2. Change the partition type to PARTITION_ENTRY_UNUSED and set the RewritePartition flag. This will cause the partition entry to be zeroed and written out to disk thus causing the volume to disappear
3. Copy the original contents of the partition entry back into the layout but change the partition type to PARTITION_IFS, again with the RewritePartition flag set to TRUE
Let me know how this goes...
Alright! This works perfectly now. The partition(s) show(s) up
immediately now.
Thanks much for those precise directions!
-georges
I'd like to complement my previous answer.
Yes, it works just fine. The partition appears immediately.
But I worry about what I have been forced to do: I have in facts deleted
a partition, to the point where the system would not find it again, then
using the saved information about that partition, I resurect it...
My problem is that there is a serious risk taken by this approach: for a
(very) short period of time, my partition is "really" gone. If for some
reason (the user pulling the plug, or any other kind of reason), the
computer goes off at that exact moment, I will loose my partition for
good. It won't be hidden, it will be simply gone.
Any idea on how I could circumvent this issue?
I guess that because I am in fact using primary partitions, and because
I "know" that I have only two primary partitions in use, I could use an
unused partition descriptor to make the partition active in that
location, before I delete the firt entry. That way, I'd guess that
windows would first discover the partition with its new type, before I'd
make it forget the other partition of the old type...
Would that work?
-georges
I really wish I had a non-destructive solution... but the volume manager currently does not provide a mechanism to "unhide" volumes. One option would be to write out the partition table on to an unused sector before modifying the MBR, so that if something were to happen, there is a recovery path
Now if none of the partitions on this disk are hosting the pagefile, there is an alternative:
1. Query the layout, change the partition type and write it out to disk, as before
2. Restart the disk node - this will indirectly cause the related volume nodes to also refresh
To restart the disk node, you will need to use the SetupDi APIs - if you aren't already using them to locate the disk:
1. SetupDiGetClassDevs(&DiskClassGuid, ...)
2. SetupDiEnumDeviceInterfaces() to iterate through the disks
3. SetupDiGetDeviceInterfaceDetail() on each one to obtain the interface detail as well as the device info data
4. Use the device path in the interface detail to open a handle to the disk so as to determine if this is the one that you are in interested in
5. Once a match is found, use the device info data to restart the node
To restart the node you will need to use SetupDiSetClassInstallParams and SetupDiCallClassInstaller with DIF_PROPERTYCHANGE and then SetupDiGetDeviceInstallParams to determine if a reboot | restart is required or not
The devcon sample in the DDK (http://msdn.microsoft.com/library/en-us/ddtools/hh/ddtools/devcon_6nzn.asp) is an excellent reference for these APIs... but if there is anything that isn't clear, feel free to ask
| I guess that because I am in fact using primary partitions, and because
| I "know" that I have only two primary partitions in use, I could use an
| unused partition descriptor to make the partition active in that
| location, before I delete the firt entry. That way, I'd guess that
| windows would first discover the partition with its new type, before I'd
| make it forget the other partition of the old type...
| Would that work?
Sadly, that won't work because the disk driver keys off the starting offset and length fields when exposing partitions. Because these would be identical, the second entry would be treated as a duplicate
Thanks!
--
Needless to say, this seems to be a pretty nice addition to think of for
a next release... :-)
> Now if none of the partitions on this disk are hosting the pagefile, there is an alternative:
>
> 1. Query the layout, change the partition type and write it out to disk, as before
> 2. Restart the disk node - this will indirectly cause the related volume nodes to also refresh
>
> To restart the disk node, you will need to use the SetupDi APIs - if you aren't already using them to locate the disk:
>
> 1. SetupDiGetClassDevs(&DiskClassGuid, ...)
> 2. SetupDiEnumDeviceInterfaces() to iterate through the disks
> 3. SetupDiGetDeviceInterfaceDetail() on each one to obtain the interface detail as well as the device info data
> 4. Use the device path in the interface detail to open a handle to the disk so as to determine if this is the one that you are in interested in
> 5. Once a match is found, use the device info data to restart the node
>
> To restart the node you will need to use SetupDiSetClassInstallParams and SetupDiCallClassInstaller with DIF_PROPERTYCHANGE and then SetupDiGetDeviceInstallParams to determine if a reboot | restart is required or not
>
> The devcon sample in the DDK (http://msdn.microsoft.com/library/en-us/ddtools/hh/ddtools/devcon_6nzn.asp) is an excellent reference for these APIs... but if there is anything that isn't clear, feel free to ask
Unfortunately, the system has only one disk and two partitions.
Thanks for all the suggestions. I'll go for that, even if I don't feel
happy about it. The window should be very small... :-( and this
operation be necessary only in specific but uncommon situations.
-georges