Esempio n. 1
0
/*****************************************************************************
 * WCMD_getfileowner
 *
 * Reverse a WCHARacter string in-place (strrev() is not available under unixen :-( ).
 */
static void WCMD_getfileowner(WCHAR *filename, WCHAR *owner, int ownerlen) {

    ULONG sizeNeeded = 0;
    DWORD rc;
    WCHAR name[MAXSTRING];
    WCHAR domain[MAXSTRING];

    /* In case of error, return empty string */
    *owner = 0x00;

    /* Find out how much space we need for the owner security descriptor */
    GetFileSecurityW(filename, OWNER_SECURITY_INFORMATION, 0, 0, &sizeNeeded);
    rc = GetLastError();

    if(rc == ERROR_INSUFFICIENT_BUFFER && sizeNeeded > 0) {

        LPBYTE secBuffer;
        PSID pSID = NULL;
        BOOL defaulted = FALSE;
        ULONG nameLen = MAXSTRING;
        ULONG domainLen = MAXSTRING;
        SID_NAME_USE nameuse;

        secBuffer = HeapAlloc(GetProcessHeap(),0,sizeNeeded * sizeof(BYTE));
        if(!secBuffer) return;

        /* Get the owners security descriptor */
        if(!GetFileSecurityW(filename, OWNER_SECURITY_INFORMATION, secBuffer,
                            sizeNeeded, &sizeNeeded)) {
            HeapFree(GetProcessHeap(),0,secBuffer);
            return;
        }

        /* Get the SID from the SD */
        if(!GetSecurityDescriptorOwner(secBuffer, &pSID, &defaulted)) {
            HeapFree(GetProcessHeap(),0,secBuffer);
            return;
        }

        /* Convert to a username */
        if (LookupAccountSidW(NULL, pSID, name, &nameLen, domain, &domainLen, &nameuse)) {
            static const WCHAR fmt[]  = {'%','s','%','c','%','s','\0'};
            snprintfW(owner, ownerlen, fmt, domain, '\\', name);
        }
        HeapFree(GetProcessHeap(),0,secBuffer);
    }
    return;
}
Esempio n. 2
0
/**************************************************************************
 * RetreiveFileSecurity [SETUPAPI.@]
 *
 * Retrieve the security descriptor that is associated with the given file.
 *
 * PARAMS
 *     lpFileName [I] Name of the file
 *
 * RETURNS
 *     Success: ERROR_SUCCESS
 *     Failure: other
 */
DWORD WINAPI RetreiveFileSecurity(LPCWSTR lpFileName,
                                  PSECURITY_DESCRIPTOR *pSecurityDescriptor)
{
    PSECURITY_DESCRIPTOR SecDesc;
    DWORD dwSize = 0x100;
    DWORD dwError;

    TRACE("%s %p\n", debugstr_w(lpFileName), pSecurityDescriptor);

    SecDesc = MyMalloc(dwSize);
    if (SecDesc == NULL)
        return ERROR_NOT_ENOUGH_MEMORY;

    if (GetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION |
                         GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
                         SecDesc, dwSize, &dwSize))
    {
      *pSecurityDescriptor = SecDesc;
      return ERROR_SUCCESS;
    }

    dwError = GetLastError();
    if (dwError != ERROR_INSUFFICIENT_BUFFER)
    {
        MyFree(SecDesc);
        return dwError;
    }

    SecDesc = MyRealloc(SecDesc, dwSize);
    if (SecDesc == NULL)
        return ERROR_NOT_ENOUGH_MEMORY;

    if (GetFileSecurityW(lpFileName, OWNER_SECURITY_INFORMATION |
                         GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
                         SecDesc, dwSize, &dwSize))
    {
      *pSecurityDescriptor = SecDesc;
      return ERROR_SUCCESS;
    }

    dwError = GetLastError();
    MyFree(SecDesc);

    return dwError;
}
Esempio n. 3
0
File: extra.c Progetto: csilles/cxxr
int winAccessW(const wchar_t *path, int mode)
{
    DWORD attr = GetFileAttributesW(path);

    if(attr == 0xffffffff) return -1;
    if(mode == F_OK) return 0;

    if(mode & X_OK)
	if(!(attr & FILE_ATTRIBUTE_DIRECTORY)) { /* Directory, so OK */
	    /* Look at extension for executables */
	    wchar_t *p = wcsrchr(path, '.');
	    if(p == NULL ||
	       !((wcsicmp(p, L".exe") == 0) || (wcsicmp(p, L".com") == 0) ||
		 (wcsicmp(p, L".bat") == 0) || (wcsicmp(p, L".cmd") == 0)) )
		return -1;
	}
    {
	/* Now look for file security info */
	SECURITY_DESCRIPTOR *sdPtr = NULL;
	DWORD size = 0;
	GENERIC_MAPPING genMap;
	HANDLE hToken = NULL;
	DWORD desiredAccess = 0;
	DWORD grantedAccess = 0;
	BOOL accessYesNo = FALSE;
	PRIVILEGE_SET privSet;
	DWORD privSetSize = sizeof(PRIVILEGE_SET);
	int error;

	/* get size */
	GetFileSecurityW(path,
			 OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION
			 | DACL_SECURITY_INFORMATION, 0, 0, &size);
	error = GetLastError();
	if (error != ERROR_INSUFFICIENT_BUFFER) return -1;
	sdPtr = (SECURITY_DESCRIPTOR *) alloca(size);
	if(!GetFileSecurityW(path,
			     OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION
			     | DACL_SECURITY_INFORMATION, sdPtr, size, &size))
	    return -1;
	/*
	 * Perform security impersonation of the user and open the
	 * resulting thread token.
	 */
	if(!ImpersonateSelf(SecurityImpersonation)) return -1;
	if(!OpenThreadToken(GetCurrentThread (),
			    TOKEN_DUPLICATE | TOKEN_QUERY, FALSE,
			    &hToken)) return -1;
	if (mode & R_OK) desiredAccess |= FILE_GENERIC_READ;
	if (mode & W_OK) desiredAccess |= FILE_GENERIC_WRITE;
	if (mode & X_OK) desiredAccess |= FILE_GENERIC_EXECUTE;

	memset(&genMap, 0x0, sizeof (GENERIC_MAPPING));
	genMap.GenericRead = FILE_GENERIC_READ;
	genMap.GenericWrite = FILE_GENERIC_WRITE;
	genMap.GenericExecute = FILE_GENERIC_EXECUTE;
	genMap.GenericAll = FILE_ALL_ACCESS;
	if(!AccessCheck(sdPtr, hToken, desiredAccess, &genMap, &privSet,
			&privSetSize, &grantedAccess, &accessYesNo)) {
	    CloseHandle(hToken);
	    return -1;
	}
	CloseHandle(hToken);
	if (!accessYesNo) return -1;

	if ((mode & W_OK)
	    && !(attr & FILE_ATTRIBUTE_DIRECTORY)
	    && (attr & FILE_ATTRIBUTE_READONLY)) return -1;
    }
    return 0;
}
Esempio n. 4
0
JNIEXPORT void JNICALL 
Java_org_gudy_azureus2_platform_win32_access_impl_AEWin32AccessInterface_copyPermissionW(
	JNIEnv *env, 
	jclass	cla, 
	jstring _fileNameIn,
	jstring _fileNameOut )
{
	WCHAR		file_name_in[2048];
	WCHAR		file_name_out[2048];
    
	if ( !jstringToCharsW( env, _fileNameIn, file_name_in, sizeof( file_name_in )-1)){

		return;
	}

	if ( !jstringToCharsW( env, _fileNameOut, file_name_out, sizeof( file_name_out )-1)){

		return;
	}

	SECURITY_INFORMATION secInfo	= DACL_SECURITY_INFORMATION;
	DWORD				 cbFileSD   = 0;
	PSECURITY_DESCRIPTOR pFileSD	= NULL;

    BOOL ok = GetFileSecurityW(file_name_in, secInfo, pFileSD, 0, &cbFileSD);

      // API should have failed with insufficient buffer.

	if ( ok ){
     
		throwException( env, "copyPermission", "GetFileSecurity ok" );

        return;

    }else if (GetLastError() == ERROR_FILE_NOT_FOUND) {

		throwException( env, "copyPermission", "from file not found" );

		return;

	}else if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {

		throwException( env, "copyPermission", "GetFileSecurity unexpected response", GetLastError() );

        return;
	
	}else{

		pFileSD	= myheapalloc( cbFileSD );
      
		if (!pFileSD) {
  
			throwException( env, "copyPermission", "no memory" );

			return;
		}

		ok = GetFileSecurityW(file_name_in, secInfo, pFileSD, cbFileSD, &cbFileSD );
      
		if (!ok) {

			myheapfree( pFileSD );

			throwException( env, "copyPermission", "GetFileSecurity", GetLastError());

			return;
		}	

		ok = SetFileSecurityW( file_name_out, secInfo, pFileSD );

	 	myheapfree( pFileSD );

		if ( !ok ){

			if (GetLastError() == ERROR_FILE_NOT_FOUND) {

				throwException( env, "copyPermission", "to file not found" );

			}else{

				throwException( env, "copyPermission", "SetFileSecurity unexpected response", GetLastError() );

			}
		}
	}
}
Esempio n. 5
0
/* return TRUE on a successful copy; otherwise, FALSE. */
BOOL
GetFileSecurityAttributes (
    PCWSTR w_source, 
    PSECURITY_ATTRIBUTES *security_attributes ) {

    PSECURITY_ATTRIBUTES destination_attributes  = NULL;
    PSECURITY_DESCRIPTOR source_descriptor       = NULL;
    PBYTE                buffer                  = NULL;
    DWORD	             size                    = 0,
                         extra                   = condor_roundup ( sizeof ( PSECURITY_DESCRIPTOR ) ),
                         last_error	             = ERROR_SUCCESS;
	BOOL	             have_security_info      = FALSE,
                         ok                      = FALSE;

	__try {

        /* first, determine the required buffer size */
        have_security_info = GetFileSecurityW ( 
            w_source,
            SACL_SECURITY_INFORMATION 
            | OWNER_SECURITY_INFORMATION
            | GROUP_SECURITY_INFORMATION
            | DACL_SECURITY_INFORMATION,
            NULL,
            0,
            &size );

        if ( !have_security_info ) {

            last_error = GetLastError ();

            __leave;

        }

        /* try and allocated the required buffer size, plus some 
        wiggle room */
        buffer = new BYTE[size + extra];

        if ( !buffer ) {

            last_error = GetLastError ();

            __leave;

        }

        /* translate the buffer into the structure we want */
        destination_attributes = (PSECURITY_ATTRIBUTES) buffer;

        /* to simplify deletion, we've allocated everything as 
        one big block: placing the descriptor at the end of 
        the attributes structure. this means we only need to 
        call delete [] once on the returned pointer */
        source_descriptor = (PSECURITY_DESCRIPTOR) 
            ( ( (ULONG) buffer ) + extra );
        destination_attributes->lpSecurityDescriptor = 
            source_descriptor;

        /* now, with the buffers allocated, get the actual 
        information we are interested in */
        have_security_info = GetFileSecurityW ( 
            w_source,
            SACL_SECURITY_INFORMATION 
            | OWNER_SECURITY_INFORMATION
            | GROUP_SECURITY_INFORMATION
            | DACL_SECURITY_INFORMATION,
            source_descriptor,
            size,
            &size );

        if ( !have_security_info ) {

            last_error = GetLastError ();

            __leave;

        }

        /* fill out the remaining parts of the security 
        attributes structure */
        destination_attributes->nLength = 
            sizeof ( PSECURITY_ATTRIBUTES );
        destination_attributes->bInheritHandle = FALSE;

        /* we made it! */
        ok = TRUE;

    }
    __finally {

        /* propagate the last error */
        SetLastError ( ok ? ERROR_SUCCESS : last_error );

        if ( !ok ) {
            *security_attributes = NULL;
            delete [] buffer;
            buffer = NULL;
        }

        *security_attributes = destination_attributes;

    }

	return ok;

}
Esempio n. 6
0
/*
** Wrapper around the access() system call.  This code was copied from Tcl
** 8.6 and then modified.
*/
int win32_access(const char *zFilename, int flags){
  int rc = 0;
  PSECURITY_DESCRIPTOR pSd = NULL;
  unsigned long size;
  PSID pSid = NULL;
  BOOL sidDefaulted;
  BOOL impersonated = FALSE;
  SID_IDENTIFIER_AUTHORITY unmapped = {{0, 0, 0, 0, 0, 22}};
  GENERIC_MAPPING genMap;
  HANDLE hToken = NULL;
  DWORD desiredAccess = 0, grantedAccess = 0;
  BOOL accessYesNo = FALSE;
  PRIVILEGE_SET privSet;
  DWORD privSetSize = sizeof(PRIVILEGE_SET);
  wchar_t *zMbcs = fossil_utf8_to_filename(zFilename);
  DWORD attr = GetFileAttributesW(zMbcs);

  if( attr==INVALID_FILE_ATTRIBUTES ){
    /*
     * File might not exist.
     */

    if( GetLastError()!=ERROR_SHARING_VIOLATION ){
      rc = -1; goto done;
    }
  }

  if( flags==F_OK ){
    /*
     * File exists, nothing else to check.
     */

    goto done;
  }

  if( (flags & W_OK)
      && (attr & FILE_ATTRIBUTE_READONLY)
      && !(attr & FILE_ATTRIBUTE_DIRECTORY) ){
    /*
     * The attributes say the file is not writable.  If the file is a
     * regular file (i.e., not a directory), then the file is not
     * writable, full stop.  For directories, the read-only bit is
     * (mostly) ignored by Windows, so we can't ascertain anything about
     * directory access from the attrib data.
     */

    rc = -1; goto done;
  }

  /*
   * It looks as if the permissions are ok, but if we are on NT, 2000 or XP,
   * we have a more complex permissions structure so we try to check that.
   * The code below is remarkably complex for such a simple thing as finding
   * what permissions the OS has set for a file.
   */

  /*
   * First find out how big the buffer needs to be.
   */

  size = 0;
  GetFileSecurityW(zMbcs,
      OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
      DACL_SECURITY_INFORMATION | LABEL_SECURITY_INFORMATION,
      0, 0, &size);

  /*
   * Should have failed with ERROR_INSUFFICIENT_BUFFER
   */

  if( GetLastError()!=ERROR_INSUFFICIENT_BUFFER ){
    /*
     * Most likely case is ERROR_ACCESS_DENIED, which we will convert to
     * EACCES - just what we want!
     */

    rc = -1; goto done;
  }

  /*
   * Now size contains the size of buffer needed.
   */

  pSd = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(), 0, size);

  if( pSd==NULL ){
    rc = -1; goto done;
  }

  /*
   * Call GetFileSecurity() for real.
   */

  if( !GetFileSecurityW(zMbcs,
          OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
          DACL_SECURITY_INFORMATION | LABEL_SECURITY_INFORMATION,
          pSd, size, &size) ){
    /*
     * Error getting owner SD
     */

    rc = -1; goto done;
  }

  /*
   * As of Samba 3.0.23 (10-Jul-2006), unmapped users and groups are
   * assigned to SID domains S-1-22-1 and S-1-22-2, where "22" is the
   * top-level authority.  If the file owner and group is unmapped then
   * the ACL access check below will only test against world access,
   * which is likely to be more restrictive than the actual access
   * restrictions.  Since the ACL tests are more likely wrong than
   * right, skip them.  Moreover, the unix owner access permissions are
   * usually mapped to the Windows attributes, so if the user is the
   * file owner then the attrib checks above are correct (as far as they
   * go).
   */

  if( !GetSecurityDescriptorOwner(pSd, &pSid, &sidDefaulted) ||
      memcmp(GetSidIdentifierAuthority(pSid), &unmapped,
             sizeof(SID_IDENTIFIER_AUTHORITY))==0 ){
    goto done; /* Attrib tests say access allowed. */
  }

  /*
   * Perform security impersonation of the user and open the resulting
   * thread token.
   */

  if( !ImpersonateSelf(SecurityImpersonation) ){
    /*
     * Unable to perform security impersonation.
     */

    rc = -1; goto done;
  }
  impersonated = TRUE;

  if( !OpenThreadToken(GetCurrentThread(),
      TOKEN_DUPLICATE | TOKEN_QUERY, FALSE, &hToken) ){
    /*
     * Unable to get current thread's token.
     */

    rc = -1; goto done;
  }

  /*
   * Setup desiredAccess according to the access priveleges we are
   * checking.
   */

  if( flags & R_OK ){
    desiredAccess |= FILE_GENERIC_READ;
  }
  if( flags & W_OK){
    desiredAccess |= FILE_GENERIC_WRITE;
  }

  memset(&genMap, 0, sizeof(GENERIC_MAPPING));
  genMap.GenericRead = FILE_GENERIC_READ;
  genMap.GenericWrite = FILE_GENERIC_WRITE;
  genMap.GenericExecute = FILE_GENERIC_EXECUTE;
  genMap.GenericAll = FILE_ALL_ACCESS;

  /*
   * Perform access check using the token.
   */

  if( !AccessCheck(pSd, hToken, desiredAccess, &genMap, &privSet,
                   &privSetSize, &grantedAccess, &accessYesNo) ){
    /*
     * Unable to perform access check.
     */

    rc = -1; goto done;
  }
  if( !accessYesNo ) rc = -1;

done:

  if( hToken != NULL ){
    CloseHandle(hToken);
  }
  if( impersonated ){
    RevertToSelf();
    impersonated = FALSE;
  }
  if( pSd!=NULL ){
    HeapFree(GetProcessHeap(), 0, pSd);
  }
  fossil_filename_free(zMbcs);
  return rc;
}
Esempio n. 7
0
void ServiceStart(BOOL aService)
{
  DWORD ThreadID,i;
  wchar_t filename[MAX_PATH],access_filename[MAX_PATH];
  InitInfo();
  InitNotify();
  {
    HANDLE token; PTOKEN_USER token_user=NULL;
    SID_IDENTIFIER_AUTHORITY SIDAuthSystem={SECURITY_NT_AUTHORITY}; PSID pSystemSid=NULL;
    if(AllocateAndInitializeSid(&SIDAuthSystem,1,SECURITY_LOCAL_SYSTEM_RID,0,0,0,0,0,0,0,&pSystemSid))
    {
      if(OpenProcessToken(GetCurrentProcess(),TOKEN_QUERY,&token))
      {
        token_user=(PTOKEN_USER)DefaultTokenInformation(token,TokenUser);
        if(token_user)
        {
          if((token_user->User.Sid)&&(pSystemSid)&&(IsValidSid(token_user->User.Sid))&&(IsValidSid(pSystemSid))&&(EqualSid(token_user->User.Sid,pSystemSid)))
            IsSystem=TRUE;
          free(token_user);
        }
        CloseHandle(token);
      }
      FreeSid(pSystemSid);
    }
  }
  //get security from file.
  EnablePrivilege(L"SeSecurityPrivilege");
  if(!pipe_sd&&GetModuleFileNameW(NULL,filename,sizeofa(filename)))
  {
    wchar_t *filename_ptr;
    DWORD res=GetFullPathNameW(filename,sizeofa(access_filename),access_filename,&filename_ptr);
    if(res&&(res<sizeofa(access_filename))&&filename_ptr)
    {
      DWORD needed;
      wcscpy(filename_ptr,ACCESS_NAMEW);
      if(!GetFileSecurityW(access_filename,DACL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION,NULL,0,&needed))
        if(GetLastError()==ERROR_INSUFFICIENT_BUFFER)
        {
          pipe_sd=(PSECURITY_DESCRIPTOR)malloc(needed);
          if(pipe_sd)
          {
            if(!GetFileSecurityW(access_filename,DACL_SECURITY_INFORMATION|SACL_SECURITY_INFORMATION,pipe_sd,needed,&needed))
            {
              free(pipe_sd);
              pipe_sd=NULL;
            }
          }
        }
    }
  }
  //create default security
  if(!pipe_sd)
  {
    PSID pAccessSid=NULL;
    PSID pSystemSid=NULL;
    SID_IDENTIFIER_AUTHORITY SIDAuthLocal={SECURITY_LOCAL_SID_AUTHORITY};
    SID_IDENTIFIER_AUTHORITY SIDAuthEveryone={SECURITY_WORLD_SID_AUTHORITY};
    SID_IDENTIFIER_AUTHORITY SIDAuthSystem={SECURITY_NT_AUTHORITY};
    DWORD sd_size=SECURITY_DESCRIPTOR_MIN_LENGTH+sizeof(ACL);
    PACL pAcl=NULL;

    if(GetAllowNetwork()?AllocateAndInitializeSid(&SIDAuthEveryone,1,SECURITY_WORLD_RID,0,0,0,0,0,0,0,&pAccessSid):AllocateAndInitializeSid(&SIDAuthLocal,1,SECURITY_LOCAL_RID,0,0,0,0,0,0,0,&pAccessSid))
    {
      if(AllocateAndInitializeSid(&SIDAuthSystem,1,SECURITY_LOCAL_SYSTEM_RID,0,0,0,0,0,0,0,&pSystemSid))
      {
        sd_size+=2*(sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD))+GetLengthSid(pAccessSid)+GetLengthSid(pSystemSid);
        pipe_sd=(PSECURITY_DESCRIPTOR)malloc(sd_size);
        if(pipe_sd)
        {
          pAcl=(PACL)(((char *)pipe_sd)+SECURITY_DESCRIPTOR_MIN_LENGTH);
          if(!(InitializeAcl(pAcl,sd_size-SECURITY_DESCRIPTOR_MIN_LENGTH,ACL_REVISION)&&AddAccessAllowedAce(pAcl,ACL_REVISION,FILE_ALL_ACCESS,pAccessSid)&&AddAccessAllowedAce(pAcl,ACL_REVISION,FILE_ALL_ACCESS,pSystemSid)&&InitializeSecurityDescriptor(pipe_sd,SECURITY_DESCRIPTOR_REVISION)&&SetSecurityDescriptorDacl(pipe_sd,TRUE,pAcl,FALSE)))
          {
            free(pipe_sd);
            pipe_sd=NULL;
          }
        }
        FreeSid(pSystemSid);
      }
      FreeSid(pAccessSid);
    }
  }
  for(i=0;i<GetThreadCount();i++)
  {
    threads[i]=CreateThread(NULL,0,ServiceStartThread,(void *)(DWORD_PTR)i,CREATE_SUSPENDED,&ThreadID);
    if(threads[i])
    {
      SetThreadPriority(threads[i],GetHearPriority());
      ResumeThread(threads[i]);
    }
  }
  WaitStartEvent(aService);
  if(aService) ReportStatusToSCMgr(SERVICE_RUNNING,NO_ERROR,0);
}
Esempio n. 8
0
BOOL WipeFileW(wchar_t *filename)
{
  DWORD Error=0,OldAttr,needed; void *SD=NULL; int correct_SD=FALSE;
  wchar_t dir[2*MAX_PATH],tmpname[MAX_PATH],*fileptr=wcsrchr(filename,L'\\');
  unsigned char *buffer=(unsigned char *)malloc(BUFF_SIZE);
  if(fileptr&&buffer)
  {
    OldAttr=GetFileAttributesW(filename);
    SetFileAttributesW(filename,OldAttr&(~FILE_ATTRIBUTE_READONLY));
    if(!GetFileSecurityW(filename,DACL_SECURITY_INFORMATION,NULL,0,&needed))
      if(GetLastError()==ERROR_INSUFFICIENT_BUFFER)
      {
        SD=malloc(needed);
        if(SD)
          if(GetFileSecurityW(filename,DACL_SECURITY_INFORMATION,SD,needed,&needed)) correct_SD=TRUE;
      }
    wcsncpy(dir,filename,fileptr-filename+1);
    dir[fileptr-filename+1]=0;
    if(GetTempFileNameW(dir,L"bc",0,tmpname))
    {
      if(MoveFileExW(filename,tmpname,MOVEFILE_REPLACE_EXISTING|MOVEFILE_WRITE_THROUGH))
      {
        HANDLE f=CreateFileW(tmpname,FILE_GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_SEQUENTIAL_SCAN,NULL);
        if(f!=INVALID_HANDLE_VALUE)
        {
          BY_HANDLE_FILE_INFORMATION info;
          if(GetFileInformationByHandle(f,&info))
          {
            unsigned long long size=(unsigned long long)info.nFileSizeLow+(unsigned long long)info.nFileSizeHigh*4294967296ULL;
            unsigned long long processed_size=0;
            while(size)
            {
              unsigned long outsize=(unsigned long)((size>=BUFF_SIZE)?BUFF_SIZE:size),transferred;
              WriteFile(f,buffer,outsize,&transferred,NULL);
              size-=outsize;
              processed_size+=outsize;
              if(UpdatePosInfo(0ULL,processed_size)) break;
            }
          }
          if((SetFilePointer(f,0,NULL,FILE_BEGIN)==INVALID_SET_FILE_POINTER)||(!SetEndOfFile(f))) Error=GetLastError();
          CloseHandle(f);
        }
        if(Error) MoveFileExW(tmpname,filename,MOVEFILE_REPLACE_EXISTING|MOVEFILE_WRITE_THROUGH);
        else if(!DeleteFileW(tmpname)) Error=GetLastError();
      }
      else
      {
        Error=GetLastError();
        DeleteFileW(tmpname);
      }
    } else Error=GetLastError();
    if(Error)
    {
      SetFileAttributesW(filename,OldAttr);
      if(correct_SD) SetFileSecurityW(filename,DACL_SECURITY_INFORMATION,SD);
    }
  }
  free(SD);
  free(buffer);
  if(Error)
  {
    SetLastError(Error);
    return FALSE;
  }
  return TRUE;
}