Visual Basic System Services
SfcGetFiles: Obtain a Listing of Protected System Files
     
Posted:   Sunday April 18, 2004
Updated:   Monday December 26, 2011
     
Applies to:   VB4-32, VB5, VB6
Developed with:   VB6, Windows XP
OS restrictions:   Windows XP, Windows 2000 Professional, and Windows Me, Windows Server 2003, Windows 2000 Server
Author:   VBnet - Randy Birch
     
 Prerequisites
None.

There is precious little documented in the SDK concerning the protected file system on Windows, and at the date of this posting there is nothing on the  SfcGetFiles() API.

Here, therefore, is my attempt at returning the listing of files returned by this call.  It seems to work, although the significance of some UDT members are not documented and thus unused in this demo.

As this is a Unicode API, the results are pointers to byte strings and thus require conversion per the GetPointerToByteStringW routine.

 BAS Module Code
None.

 Form Code
To a form add a command button (Command1), a list box (List1), a label (Label1) and a text box (Text1) along with the following code:

Option Explicit
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Copyright 1996-2011 VBnet/Randy Birch, All Rights Reserved.
' Some pages may also contain other copyrights by the author.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Distribution: You can freely use this code in your own
'               applications, but you may not reproduce 
'               or publish this code on any web site,
'               online service, or distribute as source 
'               on any media without express permission.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Private Const MAX_PATH As Long = 260
Private Const ERROR_SUCCESS As Long = 0

Private Type PROTECTED_FILES
  Filename As Long
  Filenumber As Long
End Type

Private Type PROTECTED_FILE_DATA
   unknown As Long  'RpcHandle ???
   pf As PROTECTED_FILES
End Type
   
Private Declare Sub CopyMemory Lib "kernel32" _
   Alias "RtlMoveMemory" _
  (pTo As Any, uFrom As Any, _
   ByVal lSize As Long)
   
Private Declare Function lstrlenW Lib "kernel32" _
  (ByVal lpString As Long) As Long

Private Declare Function SfcGetFiles Lib "sfcfiles.dll" _
  (ptrFiles As Long, _
   dwCount As Long) As Long

Private Declare Function ExpandEnvironmentStrings Lib "kernel32" _
   Alias "ExpandEnvironmentStringsA" _
  (ByVal lpSrc As String, _
   ByVal lpDst As String, _
   ByVal nSize As Long) As Long



Private Sub Form_Load()

   Command1.Caption = "Get Protected Files"
   Text1.Text = ""
   Label1.Caption = "System Protected Files:"
   
End Sub


Private Sub Command1_Click()

   Dim cnt As Long
   Dim bufptr As Long
   Dim dwCount As Long
   Dim nStructSize As Long
   Dim pfd As PROTECTED_FILE_DATA
     
  'pass both bufptr and dwCount variables ByRef
   If SfcGetFiles(bufptr, dwCount) = ERROR_SUCCESS Then
   
     'nothing to do if either not valid
      If (bufptr <> 0) And _
         (dwCount > 0) Then
   
        'the sizeof the PROTECTED_FILE_DATA UDT
         nStructSize = LenB(pfd)
         
        'this just speeds up filling the list
         List1.Visible = False
         
           'taking the memory address specified by bufptr
           'and jumping every nStructSize bytes, retrieve
           'each protected file into the pfd structure
            For cnt = 0 To (dwCount - 1)
                
               CopyMemory pfd, ByVal bufptr + (nStructSize * cnt), nStructSize
               
              'the string returned is a wide byte string,
              'so convert for display and add to list
               List1.AddItem GetPointerToByteStringW(pfd.pf.Filename)
               
            Next
         
         List1.Visible = True

        'reflect ListCount = dwCount.
        '(w/ 1 added as ListCount is 0-based).
         Label1.Caption = "System Protected Files: (" & List1.ListCount + 1 & ")"

      End If  'bufptr
   End If  'SfcGetFiles
   
End Sub


Private Sub List1_Click()

  'expand the environment variables to
  'valid system paths for selected item
   With List1
   
      If .ListIndex > -1 Then
         Text1.Text = ExpandEnvironment(.List(.ListIndex))
      End If
   
   End With
   
End Sub


Private Function ExpandEnvironment(ByVal sEnvironPath As String) As String

  'Parses an input string containing references
  'to one or more environment variables and
  'replaces them with their current values.
  '
  'Case is ignored. Each %VariableName% string is
  'replaced with the variable's current value.
  'The replacement rules are the same as those
  'used by the command interpreter. If the name
  'is not found, the %variableName% string is
  'left intact and returned.
  '
  'NOTE: The environment variables that correspond
  'to file system folders can be mapped to an
  'equivalent CSIDL value and obtained with
  'SHGetFolderLocation. CSIDLs are more reliable
  'than variable names and should be used if at
  'all possible.
   Dim buff As String
   Dim nSize As Long
   
   buff = Space$(MAX_PATH)
   nSize = Len(buff)

   Call ExpandEnvironmentStrings(sEnvironPath, buff, nSize)
   ExpandEnvironment = TrimNull(buff)
   
End Function


Private Function GetPointerToByteStringW(ByVal dwData As Long) As String
  
   Dim tmp() As Byte
   Dim tmplen As Long
   
   If dwData <> 0 Then
   
      tmplen = lstrlenW(dwData) * 2
      
      If tmplen <> 0 Then
      
         ReDim tmp(0 To (tmplen - 1)) As Byte
         CopyMemory tmp(0), ByVal dwData, tmplen
         GetPointerToByteStringW = tmp
         
     End If
     
   End If
    
End Function


Private Function TrimNull(startstr As String) As String

   TrimNull = Left$(startstr, lstrlenW(StrPtr(startstr)))
   
End Function
 Comments
 

 
 

PayPal Link
Make payments with PayPal - it's fast, free and secure!

 
 
 
 

Copyright 1996-2011 VBnet and Randy Birch. All Rights Reserved.
Terms of Use  |  Your Privacy

 

Hit Counter