Subject: Windows call SetFileValidData() fails on cygwin 1.5.25-15 usign gcc 3.4.4
From: [email-masked]
To: [email-masked]
Cc: [email-masked]
Date: Fri, 15 Jan 2010 13:47:54 +0100
List-Id: <cygwin.cygwin.com>

Hi all,

My aim is to allocate a (large) file on disk and write somewhere at the end
without being hit by the performance penalty of zero-filling that NTFS
executes by default.

Therefore, I try to use SetFileValidData() but this consistently reports
windows error 1314 "A required privilege is not held by the client".
(I am aware of the risks, thanks for your concern).
The error occurs on an executable that is compiled under cygwin 1.5.25-15
using gcc version 3.4.4. No error on an exec that is built with
MS visual studio .NET 2003.

Function SetFileValidData() requires a special privilege SE_MANAGE_VOLUME_NAME
that is set in the program. Program lists current priviledges to check that it
is actually set; this confirms that the permission is granted.

All other windows system calls work fine: CreateFile(), SetFilePointerEx(),
WriteFile() etc.

I tried setting all priviledges but that provides no solution.

I tried checking preprocessor output, but that does not show anything abnormal
on SetFileValidData() compared to the other calls.

Further I tried setting __W32API_USE_DLLIMPORT__ before including <windows.h>,
again without and change.

Any help is greatly appreciated!

Here is my sample program
Note: this requires c:\Temp\zzz dir to store a file.
--------------------------
/* Windows header files */
#define WIN32_LEAN_AND_MEAN 1 /* Include only what we need */
#define _WIN32_WINNT 0x0501   /* Windows Server 2003, Windows XP -  
required for
SetFileValidData() */
#include <windows.h>

/* Standard header files */
#include <stdio.h>
#include <stdlib.h>

#define MBYTE       (1024 * 1024)
#define GBYTE       (1024 * MBYTE)
#define FILESIZE    (1*(__int64)GBYTE)
#define FILENAME    "C:\\Temp\\zzz\\xx.dat"

static void ListPriviledges(HANDLE hAccessToken, char *head) {
     char str[256];
     unsigned int  i;
     DWORD dwTemp;
     TOKEN_PRIVILEGES *tp_buf;

     fprintf(stderr, "\n%s:\n", head);

     tp_buf = (TOKEN_PRIVILEGES *)malloc(2048); /* must be large enough */
     if (!GetTokenInformation(hAccessToken, TokenPrivileges, tp_buf,  
2048, &dwTemp)) {
         fprintf(stderr, "Error calling GetTokenInformation: %u  
%d\n",GetLastError(),
dwTemp);
     } else {
         for (i=0; i<tp_buf->PrivilegeCount; i++) {
             dwTemp = 255;
             if (!LookupPrivilegeName(NULL,  
&tp_buf->Privileges[i].Luid, str, &dwTemp)) {
                 fprintf(stderr, "Error calling LookupPrivilegeName:  
%u\n",GetLastError());
                 strcpy(str, "_unknown_");
                 dwTemp = (DWORD)strlen(str);
             }
             str[dwTemp] = '\0';
             fprintf(stderr, "   %32s %s\n", str,  
tp_buf->Privileges[i].Attributes ?
"enabled" : "disabled");
         }
     }
     free(tp_buf);
} /* end of ListPriviledges */

/*
  * Function SetPrivilege is copied from:
  *    http://msdn.microsoft.com/en-us/library/aa446619(VS.85).aspx
  *
  * Privilege name list:
  *    http://msdn.microsoft.com/en-us/library/bb530716(VS.85).aspx
  */
static BOOL SetPrivilege(
     HANDLE hToken,          /* access token handle */
     LPCTSTR lpszPrivilege,  /* name of privilege to enable/disable */
     BOOL bEnablePrivilege)  /* to enable or disable privilege */ {
     TOKEN_PRIVILEGES tp;
     LUID luid;

     if (!LookupPrivilegeValue(NULL, lpszPrivilege, &luid )) {
         fprintf(stderr, "SetPrivilege: LookupPrivilegeValue error: %d\n",
(int)GetLastError() );
         return FALSE;
     }

     tp.PrivilegeCount = 1;
     tp.Privileges[0].Luid = luid;
     tp.Privileges[0].Attributes = bEnablePrivilege ? SE_PRIVILEGE_ENABLED : 0;

     // Enable the privilege or disable all privileges.
     if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL)) {
         fprintf(stderr, "SetPrivilege: AdjustTokenPrivileges error: %d\n",
(int)GetLastError() );
         return FALSE;
     }

     if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
         fprintf(stderr, "SetPrivilege: The token does not have the specified
privilege.\n");
         return FALSE;
     }

     return TRUE;
} /* end of SetPrivilege */

int main(int argc, char * argv[])
{
     char * sNULL = 0;
     char buf = 127;
     DWORD dwTemp;
     LONGLONG llSize = FILESIZE;
     LARGE_INTEGER liSize;
     HANDLE hAccessToken, hFile;

     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS,  
&hAccessToken)) {
         fprintf(stderr, "OpenProcessToken failed: %u\n", GetLastError());
     }

     /* List current privileges */
     ListPriviledges(hAccessToken, "Initial priviledges");

     fprintf(stderr, "Enabling priviledge %s\n", SE_MANAGE_VOLUME_NAME);
     if (!SetPrivilege(hAccessToken, SE_MANAGE_VOLUME_NAME, TRUE)) {
         fprintf(stderr, "SetPrivilege %s failed\n", SE_MANAGE_VOLUME_NAME);
     }

     /* SETTING ALL PRIVILEGES DOES NOT HELP...
     char *privs[] = {SE_SECURITY_NAME, SE_BACKUP_NAME, SE_RESTORE_NAME,
SE_SYSTEMTIME_NAME,
         SE_SHUTDOWN_NAME, SE_REMOTE_SHUTDOWN_NAME,  
SE_TAKE_OWNERSHIP_NAME, SE_DEBUG_NAME,
         SE_SYSTEM_ENVIRONMENT_NAME, SE_SYSTEM_PROFILE_NAME,  
SE_PROF_SINGLE_PROCESS_NAME,
         SE_INC_BASE_PRIORITY_NAME, SE_CREATE_PAGEFILE_NAME,  
SE_INCREASE_QUOTA_NAME, NULL};
     int i;
     for (i=0; privs[i] != NULL; i++) {
         if (!SetPrivilege(hAccessToken, privs[i], TRUE)) {
             fprintf(stderr, "SetPrivilege %s failed\n", privs[i]);
         }
     }
     */

     /* List current privileges to check whether SE_MANAGE_VOLUME_NAME  
is really granted */
     ListPriviledges(hAccessToken, "Modified priviledges before CreateFile");

     fprintf(stderr, "Calling CreateFile\n");
     // disabling FILE_SHARE_WRITE (specify 0) is not a solution
     hFile = CreateFile(FILENAME, GENERIC_WRITE, FILE_SHARE_WRITE, 0,  
CREATE_ALWAYS, 0, 0);
     if (hFile != INVALID_HANDLE_VALUE) {
         fprintf(stderr, "Calling SetFilePointerEx\n");
         liSize.QuadPart = llSize;
         if (!SetFilePointerEx(hFile, liSize, NULL, FILE_BEGIN)) {
             fprintf(stderr, "SetFilePointerEx 1 failed: %u\n",  
GetLastError());
         }

         fprintf(stderr, "Calling SetEndOfFile\n");
         if (!SetEndOfFile(hFile)) {
             fprintf(stderr, "SetEndOfFile failed: %u\n", GetLastError());
         }

         fprintf(stderr, "Calling SetFileValidData\n");
         // setting a smaller llSize is not a solution
         if(!SetFileValidData(hFile, llSize)) {
             fprintf(stderr, "Error calling SetFileValidData: %u\n",  
GetLastError());
         }

         fprintf(stderr, "Calling SetFilePointerEx\n");
         liSize.QuadPart = llSize - 1;
         //liSize.QuadPart = llSize / 4;  /* takes 1/4 of the time to  
prove zero filling */
         if (!SetFilePointerEx(hFile, liSize, NULL, FILE_BEGIN)) {
             fprintf(stderr, "SetFilePointerEx 2 failed: %u\n",  
GetLastError());
         }

         fprintf(stderr, "Calling WriteFile\n");
         if (!WriteFile(hFile, &buf, (DWORD)1, &dwTemp, NULL) ||  
(dwTemp != 1)) {
             fprintf(stderr, "Error calling WriteFile: %u\n", GetLastError());
         }

         fprintf(stderr, "Calling CloseHandle\n");
         CloseHandle(hFile); /* Ignore error - we are done anyway */
     }

     CloseHandle(hAccessToken); /* Ignore error - we are done anyway */
     return 0;
} /* end of main */
--------------------------

Transcript of error behavior using gcc compiler/linker executed in a
cygwin bash shell:
This shows the error from SetFileValidData() and the execution takes
approx. 30 secs presumably spent in zero filling the file.
--------------------------
nlv11334@NLVHTCNXP1NB011 $ gcc -o xx xx.c; time ./xx

Initial priviledges:
             SeChangeNotifyPrivilege enabled
                 SeSecurityPrivilege disabled
                   SeBackupPrivilege disabled
                  SeRestorePrivilege disabled
               SeSystemtimePrivilege disabled
                 SeShutdownPrivilege disabled
           SeRemoteShutdownPrivilege disabled
            SeTakeOwnershipPrivilege disabled
                    SeDebugPrivilege disabled
        SeSystemEnvironmentPrivilege disabled
            SeSystemProfilePrivilege disabled
     SeProfileSingleProcessPrivilege disabled
     SeIncreaseBasePriorityPrivilege disabled
               SeLoadDriverPrivilege enabled
           SeCreatePagefilePrivilege disabled
            SeIncreaseQuotaPrivilege disabled
                   SeUndockPrivilege enabled
             SeManageVolumePrivilege disabled
              SeImpersonatePrivilege enabled
             SeCreateGlobalPrivilege enabled Enabling priviledge  
SeManageVolumePrivilege

Modified priviledges before CreateFile:
             SeChangeNotifyPrivilege enabled
                 SeSecurityPrivilege disabled
                   SeBackupPrivilege disabled
                  SeRestorePrivilege disabled
               SeSystemtimePrivilege disabled
                 SeShutdownPrivilege disabled
           SeRemoteShutdownPrivilege disabled
            SeTakeOwnershipPrivilege disabled
                    SeDebugPrivilege disabled
        SeSystemEnvironmentPrivilege disabled
            SeSystemProfilePrivilege disabled
     SeProfileSingleProcessPrivilege disabled
     SeIncreaseBasePriorityPrivilege disabled
               SeLoadDriverPrivilege enabled
           SeCreatePagefilePrivilege disabled
            SeIncreaseQuotaPrivilege disabled
                   SeUndockPrivilege enabled
             SeManageVolumePrivilege enabled
              SeImpersonatePrivilege enabled
             SeCreateGlobalPrivilege enabled Calling CreateFile  
Calling SetFilePointerEx
Calling SetEndOfFile Calling SetFileValidData Error calling  
SetFileValidData: 1314
Calling SetFilePointerEx Calling WriteFile Calling CloseHandle

real    0m30.235s
user    0m0.030s
sys     0m0.108s
nlv11334@NLVHTCNXP1NB011 $
----------------------------

Transcript of correct behavior using MS visual studio compiler/linker
executed in a cygwin bash shell:
This shows no error and the execution takes approx. 0.2 sec.
----------------------------
nlv11334@NLVHTCNXP1NB011 $ time ./Release/xx

Initial priviledges:
             SeChangeNotifyPrivilege enabled
                 SeSecurityPrivilege disabled
                   SeBackupPrivilege disabled
                  SeRestorePrivilege disabled
               SeSystemtimePrivilege disabled
                 SeShutdownPrivilege disabled
           SeRemoteShutdownPrivilege disabled
            SeTakeOwnershipPrivilege disabled
                    SeDebugPrivilege disabled
        SeSystemEnvironmentPrivilege disabled
            SeSystemProfilePrivilege disabled
     SeProfileSingleProcessPrivilege disabled
     SeIncreaseBasePriorityPrivilege disabled
               SeLoadDriverPrivilege enabled
           SeCreatePagefilePrivilege disabled
            SeIncreaseQuotaPrivilege disabled
                   SeUndockPrivilege enabled
             SeManageVolumePrivilege disabled
              SeImpersonatePrivilege enabled
             SeCreateGlobalPrivilege enabled Enabling priviledge  
SeManageVolumePrivilege

Modified priviledges before CreateFile:
             SeChangeNotifyPrivilege enabled
                 SeSecurityPrivilege disabled
                   SeBackupPrivilege disabled
                  SeRestorePrivilege disabled
               SeSystemtimePrivilege disabled
                 SeShutdownPrivilege disabled
           SeRemoteShutdownPrivilege disabled
            SeTakeOwnershipPrivilege disabled
                    SeDebugPrivilege disabled
        SeSystemEnvironmentPrivilege disabled
            SeSystemProfilePrivilege disabled
     SeProfileSingleProcessPrivilege disabled
     SeIncreaseBasePriorityPrivilege disabled
               SeLoadDriverPrivilege enabled
           SeCreatePagefilePrivilege disabled
            SeIncreaseQuotaPrivilege disabled
                   SeUndockPrivilege enabled
             SeManageVolumePrivilege enabled
              SeImpersonatePrivilege enabled
             SeCreateGlobalPrivilege enabled Calling CreateFile  
Calling SetFilePointerEx
Calling SetEndOfFile Calling SetFileValidData Calling SetFilePointerEx  
Calling WriteFile
Calling CloseHandle

real    0m0.219s
user    0m0.015s
sys     0m0.015s
nlv11334@NLVHTCNXP1NB011 $
----------------------------

Tot ziens / Kind regards, Bram
--
Bram Riemens
Senior Principal, Central R&D / Research
NXP Semiconductors

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple