Search code examples
c#wmiwinpe

MSFT_Volume Format Method, in WinPE


I hope there may be some insight and maybe help in relation to my query.

I am trying to write the last module to a customised Windows Recovery environment, based on WinPE for Windows 10.

The solution currently utilises DiskPart to create the Disk Partitions (inline with Microsoft advice here), with the change of not providing for the WinRE partition.

After a fair amount of research and tinkering with a project found on MSDN, I managed to get a working project that would clear/partition and format a disk using WMI (MSFT_Disk,MSFT_Partition & MSFT_Volume). That is fully working within Windows 10 on a virtual disk of 15 GiB size.

When I tried it in WinPE (as this will be the OS that it will be used on), it failed on multiple elements, even though the Methods were reported as there). (MSFT_Disk::Clear, MSFT_Volume::Format).

On inspecting the result of my work in DiskPart, I noticed that even though MSFT_Volume::Format had a return value of 2 "Unknown Error" it had actually formatted the data partition (NTFS, ClusterSize 4096). However, when when the Format method is applied to the ESP (FAT32, cluster size 512/1024/4096)it fails fully, with the FileSystem still being reported as RAW, but will apply an AccessPath. "ExtendedStatus" only returns Error 2 (unless I am not accessing it correctly).

Has anyone else had this problem and managed to rectify the problem? Multiple Google searches have thrown out the idea that there maybe a WMI error, but within PowerShell, not as coded in C#/C++. Below are some code snippets and screen shots:

Creating the Partition:

try
{
    parameters = disk.GetMethodParameters("CreatePartition");
}
catch (Exception e)
{
    Console.WriteLine("Exception in Line 88: " + e.Message);
}
if (PartitionType != "PRIMARY")
{
    FillInvocationParameters(parameters, new Dictionary<string, object> { { "Size", _partitionSize.ToString() },
                                                                          { "AssignDriveLetter", false },
                                                                          { "GpTType", _partitionType} });
} 
else
{
    FillInvocationParameters(parameters, new Dictionary<string, object> { { "UseMaximumSize", true },
                                                                          { "AssignDriveLetter", false },
                                                                          { "GpTType", _partitionType} });
}
try
{
    res = disk.InvokeMethod("CreatePartition", parameters, null);
    objresult = res["ReturnValue"]; //write error handliong routine for the objResult.
    Int32.TryParse(objresult.ToString(), out intRes);
}
catch (Exception e)
{
    Console.WriteLine("Exception in Line 146: " + e.Message);
    ErrorID = Marshal.GetLastWin32Error();
    return false;
}
if (intRes != 0)
{
    Console.Write("CreatePartition {0} failed with the result: {1} Line 111.", PartitionType, objresult.ToString());
    Console.ReadKey();
    ErrorID = Marshal.GetLastWin32Error();
    return false;
}
//this is the format point for EFI System Disk.. MSFTPARTITIONtoVOLUME MSFT VOLUME::FORMAT

Console.Write($"{PartitionType} Partition has been created\r\n");

string partition   = ((ManagementBaseObject)res["CreatedPartition"])["__PATH"] as string;
var MSFT_Partition = new ManagementObject(@"root\Microsoft\Windows\Storage", partition, null);
var partitionIndex = partition.IndexOf(@"ObjectId=\");

partition      = partition.Substring(partitionIndex);
partitionIndex = partition.IndexOf(@"}\\");
partitionIndex = partitionIndex + 1;
partition      = partition.Substring(0, partitionIndex);

var strMSFTPartition = partition;
partition = partition.Replace("root", "ROOT");

var partitionGuid = MSFT_Partition["Guid"] as string;
Console.WriteLine("Line 138: New Partition GUID: " + partitionGuid);

Parameters is declared as:

 ManagementBaseObject parameters = null;

FillInvokationParamters:

private static void FillInvocationParameters(ManagementBaseObject InvocationParameters, IDictionary<string, object> parameters)
{
    foreach (var pair in parameters)
    {
        string stringParamValue;

        var managementObjectParam = pair.Value as ManagementObject;
        var arrayParam = pair.Value as string;

        if (managementObjectParam != null)
        {
            stringParamValue = managementObjectParam.GetText(TextFormat.CimDtd20);
            InvocationParameters[pair.Key] = stringParamValue;
        }
        else if (arrayParam != null)
            InvocationParameters[pair.Key] = arrayParam;
        else if (pair.Value != null)
        {
            stringParamValue = pair.Value.ToString();
            InvocationParameters[pair.Key] = stringParamValue;
        }
    }
}

And the Format Method call:

try
{
    Console.Write("Line 174: Attempting to Format with MSFT_Volume::Format FileSystem {0}, Label: {1}, ClusterSize: {2}\r\n", _FileSystem, _VolumeLable, _allocationUnit.ToString());
    parameters = MSFTVolume.GetMethodParameters("Format");

    FillInvocationParameters(parameters, new Dictionary<string, object>{ { "FileSystem", _FileSystem },
                                                                             { "AllocationUnitSize", _allocationUnit },
                                                                             { "FileSystemLabel", _VolumeLable },
                                                                             { "Full", false} });

    res = MSFTVolume.InvokeMethod("Format", parameters, null);
    objresult = res["ReturnValue"];

    Int32.TryParse(objresult.ToString(), out intReslt);
}
catch (Exception e)
{
    Console.WriteLine("Line: 189 The Following error occured while attmpeting to Format the Volume: " + e.Message);
    ErrorID = Marshal.GetLastWin32Error();
    return false;
}

For the ESP the following applies:

switch(PartitionType)
{
    case "EFI":
    {
        _partitionType  = "{c12a7328-f81f-11d2-ba4b-00a0c93ec93b}";
        _partitionSize  = 260 /*bytes*/ *1024 /*Kilobytes*/ *1024 /*Megabytes*/;
        _FileSystem     = "FAT32";
        _allocationUnit = 1024;
        _VolumeLable    = "System";
        break;
    }
}

Screenshots of my console app and diskpart results:

Format Disk Console output

DiskPart Results

Any help/insights will be gratefully appreciated.

Regards

Richie


Solution

  • Note that there are several builds of the ADK for newer builds of Windows 10...be sure to use the latest and greatest. We had issues similar to yours with both dism.exe and diskpart.exe. At one point, (on early win 10 adks) we got dism.exe and diskpart.exe from an 8.1 adk. Hacky as heck, but you gotta do what you gotta do :-)

    Update:

    Checked with the support group...turns out, I got the versions mixed up. The very first win 10 adk had a working dism and diskpart (adk for windows 10 1503)...and we've been unable to use newer ones from within PE since...and so we're still deploying a new winpe from new ADK - but copying in the diskpart and dism saved off from the 1503 adk. We never deployed 8.1 versions - my bad. Still - hacky as all git out.

    Best we can recollect, it only presented a problem in one side of the house...either BIOS+MBR or UEFI+GPT...but none of us remember which.