?
Solved

How to change a files owner and permissions for NTFS in vb

Posted on 2005-04-24
11
Medium Priority
?
620 Views
Last Modified: 2013-11-23
I am looking to change a files owner in windows 2000, I have a program that runs every day as administrator which catalogs the daily batch of files. The issue i am having is that each user that sends files for the daily batch, each users has a quota of 100 megs. so every few months they run out of server space and then i must go in manualy and change the ownership of the file to my self.
It would be nice to be able to add in the ability to change owners in my program so when it catalogs the files daily, it will also change owners.
0
Comment
Question by:JesNoFear
  • 6
  • 3
  • 2
11 Comments
 
LVL 97

Expert Comment

by:Lee W, MVP
ID: 13854647
Why not just increase the quotas?
0
 
LVL 2

Author Comment

by:JesNoFear
ID: 13854697
Because of limited space on the server. And people in my company love to take advantage of what they get.
0
 
LVL 97

Expert Comment

by:Lee W, MVP
ID: 13854725
This makes no sense... you're just bypassing the Quotas for them when you take ownership.
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 2

Author Comment

by:JesNoFear
ID: 13854743
Yes, that is the intent, Because the files that are part of the daily batch go to a hiden share on the server it still counts as part of there quota. And since after they transmit the batch of files over to the server, they never use them again, it becomes an issue when they can't save there word documents to there personal server space.
0
 
LVL 41

Expert Comment

by:graye
ID: 13854765
I guess I'm confused too..   So, why are you changing the ownership of the files?   I agree with leew, in that this procedure just appears to be a way to get the owner of the file more disk quota.

Let's skip the obvious question as to "why"... and find out some more information

1) what programming platform?  VB6, VB.Net ,etc
2) you need to do this from an application (not from a batch file/command-line)?
3) you need to change the ownership to your own account?
4) you are an administrator on this server?
0
 
LVL 2

Author Comment

by:JesNoFear
ID: 13854853
Just to help make things clear, I am moving audio files (WAV Files) from 5 people's pc to the server, in addition, each user on the network has a quota of 100 megs to save work related stuff such as documents power point and other type of files. The wave files that they sent out on a daily bases i do not want to count against there quota's because once they are sent, they are never used again by them. The audio files are kepted on the server for 6 months befor being archived to tape.

I have both vb6 and vb.net but would prefer to do it in vb6, (Still learning .net) I would like to use an API or other command means of changing these files over, but as last resort i can do command line.
The program is shelled under Administrator on the server which is whom i'd like to take ownership under. (If possable to do it under the group Administrators would be best)
Yes I am the network admin and am the Administrator on the server.
Currently my program is executed via Schedule Tasks under windows 2000 server everynight. what the program dose is takes all the files from the SQL db for that day and makes sure all the files are found on the server, So it has a compleat listing of each files and where the file is located.
0
 
LVL 97

Expert Comment

by:Lee W, MVP
ID: 13854882
Why not use a different partition on the server to copy the files to?  That won't necessarily be under the quota you've set.
0
 
LVL 2

Author Comment

by:JesNoFear
ID: 13854891
that is ture, I have been trying to accomplish this a few diffrent ways, I tryed on the client end, currently they execute my program which copys all the audio files to my server, I tryed having that program run itself as an administrator, I tryed to have my program log onto the server as administrator. It would be easier to just change the permissions on the file is possable. Currently the server that it is running on we have had for 2 years and is maxed out as is, it currently has 2 hard drives with no room to spare, and since it is in the rack its kinda hard to do an external hd.
So i am kinda limited to my equiptment in that regard.
0
 
LVL 41

Accepted Solution

by:
graye earned 1600 total points
ID: 13854986
Sorry for putting you through the "3rd degree", but it's helpful for us to fully understand the question before we can provide a suitable answer.

Ok, now let's get to the answer!

There isn't a clean way to take the ownership of a file from VB6 or VB.Net...  It can be done with Windows Management Instrumentation (WMI), but that's a lot of work.  The best solution is to use the Windows APIs.   VB.Net handles Windows APIs a whole lot better than VB6, so I'd highly recommend you upgrade.

Here is an article (from http://home.hot.rr.com/graye/Articles/ChangeOwner.htm) that explains how to do what you're trying to do (using VB.Net)

As you might expect, practically all of the requirements of this example are accomplished via Windows API calls.  So, let's start with declaring the API stuff:

      Imports System.Runtime.InteropServices
      Imports System.IO
      Imports System.ComponentModel

      Private Const SE_FILE_OBJECT = 1&
      Private Const OWNER_SECURITY_INFORMATION = &H1

      Private Const NAME_SIZE = 64
      Private Const SID_SIZE = 32

      'DWORD GetNamedSecurityInfo(
      '   LPTSTR pObjectName,
      '   SE_OBJECT_TYPE ObjectType,
      '   SECURITY_INFORMATION SecurityInfo,
      '   PSID* ppsidOwner,
      '   PSID* ppsidGroup,
      '   PACL* ppDacl,
      '   PACL* ppSacl,
      '   PSECURITY_DESCRIPTOR* ppSecurityDescriptor
      ');
      Declare Auto Function GetNamedSecurityInfo Lib "AdvAPI32.DLL" ( _
            ByVal pObjectName As String, _
            ByVal ObjectType As Integer, _
            ByVal SecurityInfo As Integer, _
            ByRef ppsidOwner As IntPtr, _
            ByRef ppsidGroup As IntPtr, _
            ByRef ppDacl As IntPtr, _
            ByRef ppSacl As IntPtr, _
            ByRef ppSecurityDescriptor As IntPtr _
      ) As Integer

            'DWORD SetNamedSecurityInfo(
      '   LPTSTR pObjectName,
            '   SE_OBJECT_TYPE ObjectType,
      '   SECURITY_INFORMATION SecurityInfo,
      '   PSID psidOwner,
      '   PSID psidGroup,
      '   PACL pDacl,
      '   PACL pSacl
      ');
      Declare Auto Function SetNamedSecurityInfo Lib "AdvAPI32.DLL" ( _
            ByVal pObjectName As String, _
            ByVal ObjectType As Integer, _
            ByVal SecurityInfo As Integer, _
            ByVal psidOwner As IntPtr, _
            ByVal psidGroup As IntPtr, _
            ByVal pDacl As IntPtr, _
            ByVal pSacl As IntPtr _
      ) As Integer

      'BOOL LookupAccountName(
      '   LPCTSTR lpSystemName,
      '   LPCTSTR lpAccountName,
      '   PSID Sid,
      '   LPDWORD cbSid,
      '   LPTSTR ReferencedDomainName,
      '   LPDWORD cchReferencedDomainName,
      '   PSID_NAME_USE peUse
      ');
      Declare Auto Function LookupAccountName Lib "advapi32.dll" ( _
            ByVal lpSystemName As String, _
            ByVal lpAccountName As String, _
            ByVal Sid As IntPtr, _
            ByRef cbSid As Integer, _
            ByVal lpReferencedDomainName As String, _
            ByRef cchReferencedDomainName As Integer, _
            ByRef peUse As IntPtr _
      ) As Boolean

      Public Declare Function LocalFree Lib "kernel32" ( _
            ByVal hMem As IntPtr _
      ) As Integer

Note: As a matter of programming "style", I usually include the original C-language API definition as a comment immediately above the VB.Net Declare statement.  Obviously this is not required...
 
The guts of the program are as follows...  We take the UserName and turn it into a Security Identifier (SID), retrieve the existing security descriptor and owner, swap out the old owner with the new owner's SID, write the security descriptor back to the file

      Dim pSecDesc, pNewOwner, pOldOwner, deUse As IntPtr
      Dim Win32Error As Win32Exception
      Dim domain_name As String
      Dim ret, sid_len, domain_len As Integer
 
      ' Convert the name to a valid SID
      sid_len = SID_SIZE
      pNewOwner = Marshal.AllocHGlobal(sid_len)
      domain_len = NAME_SIZE
      domain_name = Space(domain_len)

      If LookupAccountName(Nothing, strUserName, pNewOwner, sid_len, domain_name, domain_len, deUse) = False Then
            ret = Marshal.GetLastWin32Error()
            Win32Error = New Win32Exception(ret)
            Throw New Exception(Win32Error.Message)
      End If

      ' get the Security Descriptor and Previous Owner
      ret = GetNamedSecurityInfo(strPath, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, Nothing, pOldOwner, Nothing, Nothing, pSecDesc)
      If ret <> 0 Then
            Win32Error = New Win32Exception(ret)
            Throw New Exception(Win32Error.Message)
      End If

      ' write the new Owner
      ret = SetNamedSecurityInfo(strPath, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, pNewOwner, Nothing, Nothing, Nothing)
      If ret <> 0 Then            Win32Error = New Win32Exception(ret)
            Throw New Exception(Win32Error.Message)
      End If

       ' clean up and go home
      Marshal.FreeHGlobal(pNewOwner)
      LocalFree(pSecDesc)

Now that you understand how to use API calls to change the ownership of a file, I have a small confession to make...  this example doesn't work yet.  The problem is that changing the ownership of a file is a tightly-held permission, one that is not enabled by default.  To solve this problem we need to enable the permissions for "TakeOwnership" and "Restore".

Again, to accomplish these tasks, we require lots of Windows API calls

      Imports System
      Imports System.Diagnostics
      Imports System.Runtime.InteropServices

      <StructLayout(LayoutKind.Sequential, Pack:=4)> _
      Private Structure LUID_AND_ATTRIBUTES
            Dim Luid As Long
            Dim Attributes As Integer
      End Structure

      <StructLayout(LayoutKind.Sequential, Pack:=4)> _
      Private Structure TOKEN_PRIVILEGES
            Dim PrivilegeCount As Integer
            Dim Privilege1 As LUID_AND_ATTRIBUTES
            Dim Privilege2 As LUID_AND_ATTRIBUTES
      End Structure

      <DllImport("advapi32.dll")> _
      Private Function OpenProcessToken ( _
            ByVal ProcessHandle As IntPtr, _
            ByVal DesiredAccess As Integer, _
            ByRef TokenHandle As IntPtr) As Boolean
      End Function

      <DllImport("advapi32.dll")> _
      Private Function LookupPrivilegeValue ( _
            ByVal lpSystemName As String, _
            ByVal lpName As String, _
            ByRef lpLuid As Long) As Boolean
      End Function

      <DllImport("advapi32.dll")> _
      Private Function AdjustTokenPrivileges ( _
            ByVal TokenHandle As IntPtr, _
            ByVal DisableAllPrivileges As Boolean, _
            ByRef NewState As TOKEN_PRIVILEGES, _
            ByVal BufferLength As Integer, _
            ByVal PreviousState As IntPtr, _
            ByVal ReturnLength As IntPtr) As Boolean
      End Function

      Const TOKEN_QUERY As Integer = &H8
      Const TOKEN_ADJUST_PRIVILEGES As Integer = &H20
      Const SE_TAKE_OWNERSHIP_NAME As String = "SeTakeOwnershipPrivilege"
      Const SE_RESTORE_NAME As String = "SeRestorePrivilege"
      Const SE_PRIVILEGE_ENABLED As Integer = &H2

The guts of this section is as follows...  we get the security "token" of the application, we get the privileges we need to use, then we enable those privileges.  Obviously, you can't enable privileges that you don't already have!

      Public Function SetPrivileges() As Boolean
            Dim hProc, hToken As IntPtr
            Dim luid_TakeOwnership, luid_Restore As Long
            Dim tp As New TOKEN_PRIVILEGES

            ' get the current process's token
            hProc = Process.GetCurrentProcess().Handle
            hToken = IntPtr.Zero
            If Not OpenProcessToken(hProc, TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY, hToken) Then
                  Return False
            End If

            ' get the LUIDs for the privileges (provided they already exists)
            luid_TakeOwnership = 0
            If Not LookupPrivilegeValue(Nothing, SE_TAKE_OWNERSHIP_NAME, luid_TakeOwnership) Then
                  Return False
            End If
            luid_Restore = 0
            If Not LookupPrivilegeValue(Nothing, SE_RESTORE_NAME, luid_Restore) Then
                  Return False
            End If

            tp.PrivilegeCount = 2
            tp.Privilege1.Luid = luid_TakeOwnership
            tp.Privilege1.Attributes = SE_PRIVILEGE_ENABLED
            tp.Privilege2.Luid = luid_Restore
            tp.Privilege2.Attributes = SE_PRIVILEGE_ENABLED

            ' enable the privileges
            If Not AdjustTokenPrivileges(hToken, False, tp, 0, IntPtr.Zero, IntPtr.Zero) Then
                  Return False
            End If

            Return True
      End Function
0
 
LVL 2

Author Comment

by:JesNoFear
ID: 13856630
thanks for the quick responce, Ill be able to test this out at work tommarow.
Ill let you know how it goes.
- Jes
0
 
LVL 2

Author Comment

by:JesNoFear
ID: 13887795
Sorry for the long delay, Things came up at work and have not had a chance to test it out yet.
Thanks for the quick responce though.
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The debugging module of the VB 6 IDE can be accessed by way of the Debug menu item. That menu item can normally be found in the IDE's main menu line as shown in this picture.   There is also a companion Debug Toolbar that looks like the followin…
Article by: Martin
Here are a few simple, working, games that you can use as-is or as the basis for your own games. Tic-Tac-Toe This is one of the simplest of all games.   The game allows for a choice of who goes first and keeps track of the number of wins for…
Get people started with the process of using Access VBA to control Outlook using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Microsoft Outlook. Using automation, an Access applic…
Show developers how to use a criteria form to limit the data that appears on an Access report. It is a common requirement that users can specify the criteria for a report at runtime. The easiest way to accomplish this is using a criteria form that a…
Suggested Courses

807 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question