views:

370

answers:

4

I have some old vb6 code that checks to see if the Windows directory is writeable by WRITING to it then reading a value back.

But... we have a virus scanner that's viewing that as suspicious behavior so I want to check it without touching it.

Any Windows API calls for that? (Ideally for Win 98 and above)

+3  A: 

Something to remember here is that the file system is volatile. About the only way I can see this code being used is to first do a check if a folder is writable, and then try to write something you wanted to write. The problem here is that with a volatile file system things might change in between when you make your check and when you try to write. As a consequence, you still have to be able to handle an exception if your write fails. That means the initial check is pretty much wasted. Better to put your effort into writing a better exception handler.

Additionally, for windows 2000 and later the Windows directly should only ever be writable if the user is running as an administrator. For a very long time running as an administrator was common practice, but people are starting to get the hint that this isn't a good idea. Long term, it's not a good idea for your program to do anything that requires running that way.

In fact, starting with Windows Vista, the user doesn't run anything as administrator by default, even when logged in to the administrator account. Instead, they have to manually choose to run the program as administrator or wait a security check to fail the system can prompt them to elevate.

Joel Coehoorn
The program itself handles the exception just fine. The issue here is that the *attempt* to write to the Win.ini triggers a virus warning. (The attempt fails and the program just proceeds normally but we don't want to frighten the users :-)
Clay Nichols
In that case, I suspect your AV program is watching the win.ini file itself, and not the whole folder.
Joel Coehoorn
@Joel : Good point.
Clay Nichols
AV program is watching anything that looks like a system file (win.ini, abc.dll, etc.) in the \Windows directory
Clay Nichols
+3  A: 

If you have the VB6 code, you should take the time to fix it so that it does NOT need to write to the Windows directory at all because regardless of whether or not you are an administrator - unless you work at Microsoft you should consider that directory off limits.

However, you should consider that on Windows 98, the user will always have the ability to write to the Windows directory. On Windows XP, local administrators will. On Windows Vista and Seven, even administrators will not unless your application has been elevated.

So you can check for whether or not the user is in the built-in role BUILTIN\Administrators using CheckTokenMembership. This will be false for non-admins or non-elevated processes. It does not guarantee you can write to the Windows directory but it will be right most of the time. You can then add error handling logic for when the call actually fails.

But again, you should take the opportunity to fix the code and not use the Windows directory.

Josh Einstein
A: 

For Windows 2000 and above you could use GetNamedSecurityInfo() and AccessCheck(), but I would imagine those are a pain to call from VB.

Luke
+1  A: 

Here is a function that will do it. I adapted this from some other code kind of quickly so if you use it you need to add error handling, (for instance a directory that doesn't exist just returns False. I have no idea if your anti-virus software is going to like this or not.

Function FolderIsReadOnly(ByVal FolderSpec As String) As Boolean
   Dim rst As Long
   Dim udtW32FindD As WIN32_FIND_DATA
   Dim lngFHandle As Long
   Dim strFolder As String 'set to FolderSpec parameter so I can change it

   If Len(FolderSpec) = 0 Then
      FolderIsReadOnly = False
      Exit Function
   End If

   strFolder = FolderSpec
   If Right$(strFolder, 1) <> "\" Then
      strFolder = strFolder & "\"
   End If
   strFolder = strFolder & "*"   'add the wildcard allows finding share roots

   lngFHandle = FindFirstFile(strFolder, udtW32FindD)
   If lngFHandle <> INVALID_HANDLE_VALUE Then
      Call FindClose(lngFHandle)
      FolderIsReadOnly = (udtW32FindD.dwFileAttributes And FILE_ATTRIBUTE_READONLY) = FILE_ATTRIBUTE_READONLY
   End If

End Function
Beaner