How to access hidden partitions/volumes

2019-04-15 06:04发布

问题:

I have to write a code to access hidden disk partitions/volumes using c# or c++. But could not find any help reference on the matter.

As a hidden volume, it does not contain a "Disk Letter", so you can´t just type "C:\" and access it. A example would be the "recovery partition" that comes with Windows. You can´t see it on explorer but it is there.

My application will write and read data from thoose partitions and I have to find a way of doing something like "c:\" for thoose.

In the above image, volumes 5 and 6 are hidden partitions. I have found this link on stackoverflow but it only "list" de partitions: https://msdn.microsoft.com/en-us/library/cc542456(v=VS.85).aspx

EDIT

The problem is: even using WMI as suguested I could´t find how to filter the the Volume when looking for files. Example, select * from win32_DataFile will list all Files in the machine.

I think should be a way of filtering the Volumes using their ID(or name). Something like:

select * from win32_DataFile 
where volumeId = '\\?\Volume{2d5f3a68-75f5-44c4-aa42-716b45811916}\'

Or a more beautiful way like:

var files = Directory.GetFiles(@"\\?\Volume{6ff7748e-78db-4838-8896-254b074918f5}\");

Also, I found a excelent awenser in about Partitions and Volumes (their are not the same thing) https://social.technet.microsoft.com/Forums/en-US/e7b2ddd6-f245-49ed-8fec-3b6e08e75369/how-do-i-find-the-partition-guid?forum=winservergen

EDIT2

As awensered by Harry, using "\.\Volume...." was a good way to recovery files. But I could not find a way to write(create) a new file using c#. The best approch so far is using pinvoke to c++ CreateFile method/handle.


Any advice?

回答1:

The FindFirstVolume() API returns a path to the root of each volume on the system.

For example, this code prints the path to the first volume, and the name of the first file in the root directory of that volume:

    HANDLE h1, h2;
    wchar_t volpath[4096];
    WIN32_FIND_DATA find_data;

    h1 = FindFirstVolume(volpath, _countof(volpath));

    printf("%ws\n", volpath);

    wcscat_s(volpath, _countof(volpath), L"*.*");

    h2 = FindFirstFile(volpath, &find_data);

    printf("%ws\n", find_data.cFileName);

(In production code, you would need to add error checking, etc.)

Addendum

FindFirstVolume returns a path like this: \\?\Volume{6ff7748e-78db-4838-8896-254b074918f5}\

If you're using the Win32 API (CreateFile, etc.) in C++ you can use that path directly, but due to a bug or limitation in .NET it doesn't work with file management classes such as Directory.GetFiles(). (You could P/Invoke to the Win32 API, of course, but that's awkward.)

Instead, you can work around the problem by replacing the question mark that appears at the beginning of the path with a dot:

var files = Directory.GetFiles(@"\\.\Volume{6ff7748e-78db-4838-8896-254b074918f5}\");


回答2:

If your program is Windows specific you can work with WMI. I worked a lot with WMI and it is very Handy to do any Kind of Manipulation or getting data about Windows Systems.

First of all you can download the wmiexplorer to see the available data and classes. the relevant Namespace for you will be root\cimv. There you can find various interesting classes for you:

  • Win32_LogicalDisk: Contains all disks, also hidden ones.
  • CIM_Directory: Contains all directories (As far as I know also from hidden Disks)
  • CIM_DataFile: Contains all files (I also think this one contains also the files from hidden disks)
  • There are many more classes you can use e.g. to retrieve file permissions... Microsoft has a pretty good documentation about it

Next, you can implement your desired WMI queries into your C# (or VB.NET) program. For example, this one will print all disks:

WqlObjectQuery wqlQuery = new WqlObjectQuery("SELECT * FROM Win32_LogicalDisk");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(wqlQuery);

foreach (ManagementObject disk in searcher.Get()) 
{
    Console.WriteLine(disk.ToString());
}

As you can seen, WMI supports queries like SQL (although it's not as powerful...)

WMI also supports methots for most of ist classes. For example you can check each disk for Errors:

foreach (ManagementObject disk in searcher.Get()) 
{
    if(shouldCheckThisDisk)
        disk.Chkdsk();
}