cottonmouth

Hi all,

I'm creating a backup application and I need to be able to read from and write to any file in the computer. This includes system protected and files locked by other processes. Currently I'm trying to read the registry files in the C:\WINDOWS\system32\config directory. My code successfully acquires the SE_BACKUP_NAME privilege, can get HANLDEs to the files using CreateFile, and can retrieve the files' sizes using GetFileSizeEx. However, when it tries to start reading the contents of the files using BackupRead, it always failed with an error code 5 (Access denied). The code is somehow long so I'll just post here the codes for CreateFile and BackupRead.

Code Block

// Before CreateFile is called, SE_BACKUP_NAME privilege is acquired


// CreateFile succeeds

HANDLE hFile = CreateFile(

szFile[i], // "C:\\WINDOWS\\system32\\config\\SAM" and the others

READ_CONTROL,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL
);


DWORD dwBytesToRead = 32768;
DWORD dwBytesRead = 0;
BYTE buf[32768];
LPVOID lpContext = NULL;


// BackupRead fails with error 5

if ( BackupRead(hFile, buf, dwBytesToRead, &dwBytesRead, FALSE, TRUE, &lpContext) )
{

printf("Able to read %s!\n", szFile[i]);
}
else
{
ShowError(GetLastError()); // prints the last error using FormatMessage
}

Is there something that I have to do before calling BackupRead Would BackupRead be enough to read other "non-normal" files as well MSDN documents BackupRead as the function to be used for performing backup operations. I've dgged around forums, but I still haven't seen anyone successful with this. I hope you guys can help.

Lastly, I haven't tried it yet, but would BackupWrite also encounter the same problem (even when SE_RESTORE_NAME is acquired)

Thank you very much.



Re: Visual C++ General BackupRead "Access denied" Problem (and backing up files in general)

Ramkrishna Pawar

Where and how is this BackupRead implemented






Re: Visual C++ General BackupRead "Access denied" Problem (and backing up files in general)

markrgli

Ramkrishna Pawar wrote:

Where and how is this BackupRead implemented



Here is a link to Microsoft's documentation of the function: http://msdn2.microsoft.com/en-us/library/aa362509.aspx.

Thanks.





Re: Visual C++ General BackupRead "Access denied" Problem (and backing up files in general)

Ramkrishna Pawar

Are you running this on Vista Is the application running under non-admin user's context






Re: Visual C++ General BackupRead "Access denied" Problem (and backing up files in general)

Ramkrishna Pawar

Comment from MSDN: a backup application must have access to the system-level access control settings, the ACCESS_SYSTEM_SECURITY flag must be specified in the dwDesiredAccess parameter value passed to CreateFile.




Re: Visual C++ General BackupRead "Access denied" Problem (and backing up files in general)

markrgli

I'm sorry I didn't include those information in my earlier post. I'm running it on XP Professional. I'm running it under my account, which displays as "Computer administrator" in the User Accounts window.





Re: Visual C++ General BackupRead "Access denied" Problem (and backing up files in general)

markrgli

Thanks for the help. I tried READ_CONTROL | ACCESS_SYSTEM_SECURITY in CreateFile, but BackupRead still fails. I also tried running the code under the "Administrator" user, but still BackupRead fails.





Re: Visual C++ General BackupRead "Access denied" Problem (and backing up files in general)

Ramkrishna Pawar

I dont see any reason of failure then...






Re: Visual C++ General BackupRead "Access denied" Problem (and backing up files in general)

markrgli

Hmmm... I might be doing something wrong here. If you don't mind, below is my code. Thanks for the help.

Code Block

#include "stdafx.h"

#include <Windows.h>
#include <msi.h>

// typedefs
typedef BOOL (WINAPI* pGetFileSizeEx)(HANDLE, PLARGE_INTEGER);

///////////////////////////////////////////////////////////////////////
// Utility function to display the string representation of a Win32 error code.
///////////////////////////////////////////////////////////////////////
void ShowLastError(DWORD err)
{
LPTSTR buf;

if (::FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
err,
0,
(LPTSTR) &buf,
0,
NULL) == 0)
{

}
else
{
printf("%d: %s\n", err, buf);
::LocalFree(buf);
}
}


///////////////////////////////////////////////////////////////////////
// Use this function to grant the current process the specified privilege.
// This code is copied from Microsoft's website (http://msdn2.microsoft.com/en-us/library/Aa387705.aspx)
///////////////////////////////////////////////////////////////////////
HRESULT ModifyPrivilege(
IN LPCTSTR szPrivilege,
IN BOOL fEnable)
{
HRESULT hr = S_OK;
TOKEN_PRIVILEGES NewState;
LUID luid;
HANDLE hToken = NULL;

// Open the process token for this process.
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&hToken ))
{
printf("Failed OpenProcessToken\n");
return ERROR_FUNCTION_FAILED;
}

// Get the local unique ID for the privilege.
if ( !LookupPrivilegeValue( NULL,
szPrivilege,
&luid ))
{
CloseHandle( hToken );
printf("Failed LookupPrivilegeValue\n");
return ERROR_FUNCTION_FAILED;
}

// Assign values to the TOKEN_PRIVILEGE structure.
NewState.PrivilegeCount = 1;
NewState.Privileges[0].Luid = luid;
NewState.Privileges[0].Attributes = (fEnable SE_PRIVILEGE_ENABLED : 0);

// Adjust the token privilege.
if (!AdjustTokenPrivileges(hToken,
FALSE,
&NewState,
0,
NULL,
NULL))
{
printf("Failed AdjustTokenPrivileges\n");
hr = ERROR_FUNCTION_FAILED;
}

// Close the handle.
::CloseHandle(hToken);

return hr;
}

///////////////////////////////////////////////////////////////////////
// Main function
///////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[])
{
// Acquire the SE_BACKUP_NAME privilege
HRESULT hr = ModifyPrivilege(SE_BACKUP_NAME, TRUE);

if (!SUCCEEDED(hr))
printf("Failed to modify privilege.\n");
else
printf("Successfully modified privilege.\n");

LPTSTR szFile[] = {
"C:\\Documents and Settings\\<USER>\\Local Settings\\Application Data\\Microsoft\\Windows\\UsrClass.dat",
// Registry files
"C:\\WINDOWS\\system32\\config\\SAM",
"C:\\WINDOWS\\system32\\config\\Software",
"C:\\WINDOWS\\system32\\config\\System",
"C:\\WINDOWS\\system32\\config\\Security",
"C:\\WINDOWS\\system32\\config\\Default",
"C:\\WINDOWS\\system32\\config\\UserDiff",
"C:\\Documents and Settings\\<USER>\\NTUser.dat",
};

// Load the kernel32 library
HMODULE hLib = ::LoadLibrary("kernel32");

// Get the address of GetFileSizeEx. I had to do this since my MSVC wouldn't recognize GetFileSizeEx
pGetFileSizeEx pf = (pGetFileSizeEx) GetProcAddress(hLib, "GetFileSizeEx");

printf("GetFileSizeEx's address: 0x%0x\n", pf);

for (int i = 0; i < 8; i++)
{
// Open the file
HANDLE hFile = ::CreateFile(
szFile[i], //
READ_CONTROL | ACCESS_SYSTEM_SECURITY, //
FILE_SHARE_READ, // share for reading
NULL, // default security
OPEN_EXISTING, // existing file only
FILE_FLAG_BACKUP_SEMANTICS, // open the file for backup. you will need this flag.
NULL
);

if (hFile == INVALID_HANDLE_VALUE)
{
ShowLastError(GetLastError());
}
else
{
if (hLib && pf)
{
// Now let us get the file's size.
LARGE_INTEGER size;

if ( pf(hFile, &size) )
{
printf("Size: %d\n", size.QuadPart);
}
else
{
printf("Failed to retrieve file's size.\n");
}
}
else
{
printf("Kernel32 could not be loaded.\n");
ShowLastError(GetLastError());
}

// We now read the file's contents.
const DWORD dwBytesToRead = 32768;
DWORD dwBytesRead = 0;
BYTE buf[dwBytesToRead];
LPVOID lpContext = NULL;

if ( BackupRead(hFile, buf, dwBytesToRead, &dwBytesRead, FALSE, TRUE, &lpContext) )
{
printf("Able to read %s!\n", szFile[i]);

for (int i = 0; i < dwBytesRead; i++)
putc(buf[i], stdout);
}
else
{
ShowLastError(GetLastError());
}

// Close handle
::CloseHandle(hFile);
}
}

if (hLib)
::FreeLibrary(hLib);

return 0;
}








Re: Visual C++ General BackupRead "Access denied" Problem (and backing up files in general)

Simple Samples

This question is actually outside the scope of this forum. There are many other forums in which you will get better help. Really. If you want the best help, use a forum in which this is within it's scope. You can find other forums using the Communities tab in MSDN and/or the Communities menu in Visual Studio.

The microsoft.public.platformsdk.security newsgroup is also useful.