ReadFile fails with ERROR_INVALID_FUNCTION when trying to read volume

Answered ReadFile fails with ERROR_INVALID_FUNCTION when trying to read volume

  • Wednesday, December 21, 2011 8:47 PM
     
      Has Code

    Hi,

     I am writing a application which copies the one volume to another (Volume Copy). When we try to read from volume using ReadFile API we get a error code ERROR_INVALID_FUNCTION. What are the reasons ans solution to this problem?

    I am using W2k3 system

    I am having Admin access(I can open the volume. CreateFile returns success)

    Memory allocated using VirtualAlloc which is aligned

    // VolumeRead.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    #include <windows.h>
    #include <conio.h>
    #include <iostream>
    #include <string>
    using namespace std;
    
    HANDLE gvolumehandle;
    int gbuffsize = 1024*1024*10;// 10 MB data read for test
    
    // This function enables backup and restore priviliges for this process. If
    // the priviliges are not granted that is silently ignored.
    BOOL
    EnableBackupPrivileges()
    {
        HANDLE hToken;
        BYTE buf[sizeof(TOKEN_PRIVILEGES) * 3];
        TOKEN_PRIVILEGES *tkp = (TOKEN_PRIVILEGES *) buf;
    
        if (!OpenProcessToken(GetCurrentProcess(),
            TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
            return FALSE;
    	 
    
        if (!LookupPrivilegeValue(NULL, SE_BACKUP_NAME, &tkp->Privileges[0].Luid))
            return FALSE;
    
    	
        if (!LookupPrivilegeValue(NULL, SE_RESTORE_NAME, &tkp->Privileges[1].Luid))
            return FALSE;
    
    	if (!LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &tkp->Privileges[2].Luid))
            return FALSE;
    
        tkp->PrivilegeCount = 3;
        tkp->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        tkp->Privileges[1].Attributes = SE_PRIVILEGE_ENABLED;
    	tkp->Privileges[2].Attributes = SE_PRIVILEGE_ENABLED;
    
        return AdjustTokenPrivileges(hToken, FALSE, tkp, sizeof buf, NULL, NULL);
    }
    
    int OpenVolume(wstring volumename)
    {
    	DWORD accessflags = GENERIC_READ|FILE_GENERIC_READ;
    	DWORD sharemode = FILE_SHARE_READ|FILE_SHARE_WRITE;
    	DWORD creationflags = OPEN_EXISTING;
    	DWORD attributes = FILE_FLAG_BACKUP_SEMANTICS |FILE_FLAG_SEQUENTIAL_SCAN;
    	
    	wstring volname = volumename;
    	volname += L":";
    	volname += L"\\";
    	
    	WCHAR volumenamebuffer[1024] = {0};
    	int volumenamebufferlength = 1024;
    
    	wcout << L"Getting volume name for volume " << volumename << L"\n";
    
    	if( 0 == GetVolumeNameForVolumeMountPoint(volname.c_str(),volumenamebuffer,volumenamebufferlength))
    	{		
    		DWORD status = ::GetLastError();
    		cout << "Getting volume name for volume " << volumename.c_str() << " failed. Error code = " <<status << "\n";
    		return FALSE;
    	}
    
    	volname = volumenamebuffer;
    
    	wcout << L"Opening volume " << volname << L"\n";
    
    	HANDLE temphandle = INVALID_HANDLE_VALUE;
    	gvolumehandle = CreateFile(volname.c_str(),accessflags,sharemode,NULL,creationflags,attributes,temphandle);
    	if(INVALID_HANDLE_VALUE == gvolumehandle)
    	{
    		DWORD status = ::GetLastError();
    		wcout << L"Opening volume " << volname<< L" failed. Error code = " <<status<< L"\n";
    		return FALSE;
    	}
    
    	wcout << L"Opening volume " << volname << L" completed." << L"\n";
    	return TRUE;
    }
    
    int ReadVolume(BYTE* buffstart, int buffsize)
    {
    	DWORD bytestoread = buffsize;
    	DWORD actualbytesread = 0;
    	DWORD totalbytesread = 0;
    	
    	while(1)
    	{		
    		int status = ReadFile(gvolumehandle,
    								buffstart+totalbytesread,
    								bytestoread,
    								&actualbytesread,
    								NULL);		
    
    		// update remaining bytes
    		bytestoread -= actualbytesread;
    
    		// update total bytes
    		totalbytesread += actualbytesread;
    
    		// check for read complete
    		if(status != 0)
    		{
    			//read successfull
    			if(totalbytesread == buffsize)
    			{
    				//successfully read all bytes				
    				return true;
    			}	
    			else
    			{
    				// we read some bytes only so continue reading				
    				continue;
    			}
    		}	
    		else
    		{		
    			// read failed
    			DWORD errorcode = ::GetLastError();
    			if(errorcode  == ERROR_HANDLE_EOF)
    			{			
    				cout << "ReadFile failed. no more data to read. Error code = " << errorcode << "\n";
    				return true;
    			}
    			return false;
    		}
    	}
    	return false;	
    }
    
    
    int ReadVolume(wstring sourcevolume)
    {
    	cout << "Opening volume.\n";
    	if(TRUE != OpenVolume(sourcevolume))
    	{
    		cout << "Opening volume failed.\n";
    		return false;
    	}
    	cout << "Opening volume completed.\n";
    	
    	
    	BYTE* buff = (BYTE*)VirtualAlloc(NULL,gbuffsize,MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE);
    	cout << "Reading volume .\n";
    	ReadVolume(buff,gbuffsize);
    	cout << "Reading volume completed.\n";
    
    	return 0;
    }
    int _tmain(int argc, _TCHAR* argv[])
    {
    	gvolumehandle = INVALID_HANDLE_VALUE;
    	wstring sourcevolume;
    	cout << "Please enter source volume. (only name of volume single char) ";
    	wcin >> sourcevolume;	
    
    	BOOL prv = EnableBackupPrivileges();
    
    	ReadVolume(sourcevolume);
    	return 0;
    }
    
    
    


All Replies

  • Monday, April 02, 2012 8:51 PM
     
     Answered

    I fixed the error.

     The main reason to get this error was invalid path. I was opening the volume where volume name was ended with \e.g c:\.

    This opens file system on volume not volume itself(create file does not return error if u end volume name with \). Changing volume name fixed the problem

    • Marked As Answer by HemantKulkarni Monday, April 02, 2012 8:51 PM
    •