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

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

 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

  Filename As Long
  Filenumber As Long
End Type

   unknown As Long  'RpcHandle ???
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
  '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(
         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


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