We help IT Professionals succeed at work.

We've partnered with Certified Experts, Carl Webster and Richard Faulkner, to bring you two Citrix podcasts. Learn about 2020 trends and get answers to your biggest Citrix questions!Listen Now

x

Locking a volume on Windows XP using FSCTL_LOCK_VOLUME

Medium Priority
3,878 Views
Last Modified: 2013-12-03
I'm writing a disk utility that will need to directly write to a volume; thus, for compatibility with Vista, I'd like to lock that volume before writing to it.  Whenever I try issuing a FSCTL_LOCK_VOLUME or FSCTL_DISMOUNT_VOLUME command, the call always fails with GetLastError() == 5, error ACCESS_DENIED.  I read that this can be due to anti-virus software that locks up the volume, so I tried disabling McAfee anti-virus; no go.  I opened ProcessExplorer and found that Windows Security Center may have had a handle to the volume, so I disabled it; still didn't work.  I did a search for all handles with the word "volume" in it and found one svchost.exe instance that had a handle to \Device\HarddiskVolume1, so I killed that process; still didn't work.  I even confirmed with another search that there were no more handles with the word "volume" in them anywhere (although there was a handle to \Device\Harddisk0 open in the System process).

I'm not sure why I keep getting this access denied error; I can't locate any program that may have a handle open to the volume, and I've confirmed that I'm running on an account with Administrator privileges.  To confirm that it wasn't just my code, I tried running CHKDSK, once with the /f flag and once with the /x flag, and both times it reported that it couldn't lock the volume.  I've replicated these conditions on two different machines running XP SP 2, and I just can't figure out what's wrong.

Here's how my code opens the volume handle:

HANDLE volume_handle;
volume_handle = CreateFile(
            "\\\\?\\C:",
            GENERIC_READ | GENERIC_WRITE,
            FILE_SHARE_READ | FILE_SHARE_WRITE,
            NULL,
            OPEN_EXISTING,
            NULL,
            NULL);
if (volume_handle == INVALID_HANDLE_VALUE)
      {
            printf("Failed to open handle to drive %c: - error code %u", drive, GetLastError());
            return 0;
      }

The program always passes that point, so I assume I have a good handle.  Here's how I attempt to lock the volume:

if (!DeviceIoControl(
            volume_handle,
            FSCTL_LOCK_VOLUME,
            NULL,
            0,
            NULL,
            0,
            &bytes_returned,
            NULL))
      {
            if (force) //User chose to force dismount, but even so, I always see the error message.
            {
                  if (!DeviceIoControl(
                        volume_handle,
                        FSCTL_DISMOUNT_VOLUME,
                        NULL,
                        0,
                        NULL,
                        0,
                        &bytes_returned,
                        NULL))
                  {
                        printf("Failed to force dismount - error code %u.\n", GetLastError());
                        return 0;
                  }
            }
        }

I'm inclined to think it's an environment problem rather than something specific to my code, since CHKDSK fails as well.  Did XP simply disable this feature or something?

Any help would be greatly appreciated.
Comment
Watch Question

jkr
CERTIFIED EXPERT
Top Expert 2012

Commented:
See the docs on that control code (http://msdn.microsoft.com/en-us/library/aa364575(VS.85).aspx), they clearly state that "This operation fails if there are any open files on the volume".

Author

Commented:
I had read that before, and ensured that there were no programs running in the task bar.  However, I never thought to check that all file handles were closed via Process Explorer, so I'll try doing that next.
jkr
CERTIFIED EXPERT
Top Expert 2012

Commented:
Are you booting from 'c:'?

Author

Commented:
Yes, I am.  I imagine this makes the operation a bit unfeasible; there are numerous system processes that have handles to various files on the volume.  So, what are my options?  Do I have to figure out another way to run the utility, or is there a way to truly force the volume to lock, despite open handles?  Given the number of them, it would seem like a hassle to close all the handles manually.
jkr
CERTIFIED EXPERT
Top Expert 2012

Commented:
You cannot even close all the handles manually - that would not work either, since yozu cannot close kernel handles. However, you could run that the same way Windows runs 'Autochk' using 'HKLM\System\CurrentControlSet\Control\Session Manager\BootExecute' - see http://technet.microsoft.com/en-us/sysinternals/bb897447.aspx ("Inside Native Applications")
jkr
CERTIFIED EXPERT
Top Expert 2012

Commented:
Sorry, forgot that MS has removed a lot from the original article, which you can find here: http://web.archive.org/web/20060427071811/www.sysinternals.com/Information/NativeApplications.html

The source code is
//======================================================================
//
// Native.h
//
// Mark Russinovich
// http://www.ntinternals.com
//
// This file includes the definitions required by the Native.exe sample
// NT native program to do what it does. 
//
//======================================================================
 
//
// Environment information, which includes command line and
// image file name
//
typedef struct {
       ULONG            Unknown[21];     
       UNICODE_STRING   CommandLine;
       UNICODE_STRING   ImageFile;
} ENVIRONMENT_INFORMATION, *PENVIRONMENT_INFORMATION;
 
//
// This structure is passed as NtProcessStartup's parameter
//
typedef struct {
       ULONG                     Unknown[3];
       PENVIRONMENT_INFORMATION  Environment;
} STARTUP_ARGUMENT, *PSTARTUP_ARGUMENT;
 
//
// Data structure for heap definition. This includes various
// sizing parameters and callback routines, which, if left NULL,
// result in default behavior
//
typedef struct {
	ULONG    	Length;
	ULONG    	Unknown[11];
} RTL_HEAP_DEFINITION, *PRTL_HEAP_DEFINITION;
 
//
// Native NT api function to write something to the boot-time
// blue screen
//
NTSTATUS 
NTAPI 
NtDisplayString(
		PUNICODE_STRING String 
		);
 
//
// Native applications must kill themselves when done - the job
// of this native API
//
NTSTATUS 
NTAPI 
NtTerminateProcess(
		   HANDLE ProcessHandle, 
		   LONG ExitStatus 
		   );
 
//
// Definition to represent current process
//
#define NtCurrentProcess() ( (HANDLE) -1 )
 
//
// Heap creation routine
//
HANDLE 
NTAPI 
RtlCreateHeap(
	      ULONG Flags, 
	      PVOID BaseAddress, 
	      ULONG SizeToReserve, 
	      ULONG SizeToCommit, 
	      PVOID Unknown,
	      PRTL_HEAP_DEFINITION Definition
	      );
 
//
// Heap allocation function (ala "malloc")
//
PVOID 
NTAPI 
RtlAllocateHeap(
		HANDLE Heap, 
		ULONG Flags, 
		ULONG Size 
		);
 
//
// Heap free function (ala "free")
//
BOOLEAN 
NTAPI 
RtlFreeHeap(
	    HANDLE Heap, 
	    ULONG Flags, 
	    PVOID Address 
	    );
 
 
//======================================================================
//
// Native.c
//
// Mark Russinovich
// http://www.ntinternals.com
//
// This is a demonstration of a Native NT program. These programs
// run outside of the Win32 environment and must rely on the raw
// services provided by NTDLL.DLL. AUTOCHK (the program that executes
// a chkdsk activity during the system boot) is an example of a
// native NT application.
//
// This example is a native 'hello world' program. When installed with
// the regedit file associated with it, you will see it print 
// "hello world" on the initialization blue screen during the system
// boot. This program cannot be run from inside the Win32 environment.
//
//======================================================================
#include "ntddk.h" // include this for its native functions and defn's
#include "stdio.h"
#include "native.h"
 
//
// Our heap
//
HANDLE Heap;
 
//----------------------------------------------------------------------
//
// NtProcessStartup
//
// Instead of a 'main' or 'winmain', NT applications are entered via
// this entry point.  
//
//----------------------------------------------------------------------
void NtProcessStartup( PSTARTUP_ARGUMENT Argument )
{
    PUNICODE_STRING commandLine;
    PWCHAR stringBuffer, argPtr;
    UNICODE_STRING helloWorld;
    RTL_HEAP_DEFINITION  heapParams;
 
    //
    // Initialize some heap
    //
    memset( &heapParams, 0, sizeof( RTL_HEAP_DEFINITION ));
    heapParams.Length = sizeof( RTL_HEAP_DEFINITION );
    Heap = RtlCreateHeap( 2, 0, 0x100000, 0x1000, 0, &heapParams );
 
    //
    // Point at command line
    //
    commandLine = &Argument->Environment->CommandLine;
 
    //
    // Locate the argument
    //
    argPtr = commandLine->Buffer;
    while( *argPtr != L' ' ) argPtr++;
    argPtr++;
 
    //
    // Print out the argument
    //
    stringBuffer = RtlAllocateHeap( Heap, 0, 256 );
    swprintf( stringBuffer, L"\n%s", argPtr );
    helloWorld.Buffer = stringBuffer;
    helloWorld.Length = wcslen( stringBuffer ) * sizeof(WCHAR);
    helloWorld.MaximumLength = helloWorld.Length + sizeof(WCHAR);
    NtDisplayString( &helloWorld );
 
    //
    // Free heap
    //
    RtlFreeHeap( Heap, 0, stringBuffer );
 
    //
    // Terminate
    //
    NtTerminateProcess( NtCurrentProcess(), 0 );
}

Open in new window

Author

Commented:
So, it's going to be impossible for me to write directly to the volume that I boot from?  How do programs like Partition Magic work then; Device Driver Kit?

Although the native NT applications look interesting as well.  Since they run outside the OS, would I be able to use the Assembly-level int 13h disk access functions that Win32 typically blocks?  If that's the case, I have an old DOS version of the utility that might be a good candidate for running in this manner.
CERTIFIED EXPERT
Top Expert 2012
Commented:
Well, Partition Magic probably installs a driver to accomplish that, which would be anothre option.

I'd not rely on any assembly-level interrupts to be available at that level, since even you run outside of Win32, you still have a fully fledged NT executive that you run on.

Not the solution you were looking for? Getting a personalized solution is easy.

Ask the Experts

Author

Commented:
Well, thanks for all your help.  I may just finish the DOS version of the utility, but I'm also going to look into a few more methods of achieving the disk I/O I need on Windows.
Access more of Experts Exchange with a free account
Thanks for using Experts Exchange.

Create a free account to continue.

Limited access with a free account allows you to:

  • View three pieces of content (articles, solutions, posts, and videos)
  • Ask the experts questions (counted toward content limit)
  • Customize your dashboard and profile

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

OR

Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.