Eigentümer einer Datei auslesen

Anfängerfragen zum Programmieren mit PureBasic.
CelAthor
Beiträge: 6
Registriert: 16.06.2006 10:01

Eigentümer einer Datei auslesen

Beitrag von CelAthor »

Ich schlage mich schon ein wenig mit Access Control Lists rum, es hapert im Moment beim Auslesen des Owners einer Datei.
Beim Aufruf von GetSecurityDescriptorOwner_ erhalte ich immer einen "Invaild Memory Access"... :roll:

Code: Alles auswählen

#OWNER_SECURITY_INFORMATION = 4
szfilename.s = Space(#MAX_PATH)
szfilename="E:\"
sizeSD.l
bSuccess = GetFileSecurity_(szfilename,#OWNER_SECURITY_INFORMATION,0,0,@sizeSD)
Dim sdbuf.b(sizeSD-1)
bSuccess = GetFileSecurity_(szfilename,#OWNER_SECURITY_INFORMATION,sdbuf(),sizeSD,@sizeSD)
If bSuccess=0
  MessageRequester("Error",Str(GetLastError_()))
EndIf
lngdummy.l
*powner.l
GetSecurityDescriptorOwner_(sdbuf(),*powner,lngdummy)
Debug powner
Evtl. weiß jemand, wo der Fehler liegt...
Benutzeravatar
Shardik
Beiträge: 746
Registriert: 25.01.2005 12:19

Beitrag von Shardik »

Das können auch andere hinbekommen: :wink:
Beispielprogramm (getestet unter WinNT 4 SP6 und WinXP SP2), konvertiert aus dem VisualBASIC 6 Sourcecode von:
http://www.activevb.de/tipps/vb6tipps/tipp0683.html

Code: Alles auswählen

Procedure.S GetLastError()
  ErrorBufferPointer.L
  ErrorCode.L
  ErrorText.S
  
  ErrorCode = GetLastError_() 
  ferr = FormatMessage_(#FORMAT_MESSAGE_ALLOCATE_BUFFER | #FORMAT_MESSAGE_FROM_SYSTEM, 0 , ErrorCode, GetUserDefaultLangID_(), @ErrorBufferPointer, 0, 0)
  If ErrorBufferPointer <> 0 
    ErrorText = PeekS(ErrorBufferPointer) 
    LocalFree_(ErrorBufferPointer) 
    ProcedureReturn RemoveString(ErrorText, #CRLF$) 
  EndIf
EndProcedure


#OWNER_SECURITY_INFORMATION = 1

AccountName.S
AccountNameSize.L
AdditionalBytesNeeded.L
DomainName.S
DomainNameSize.L
FolderName.S
Path.S
SIDPointer.L
SIDDefaultedPointer.L
SIDType.L
ReturnCode.L
SecurityDescriptorBuffer.L 
SecurityDescriptorBufferSize.L

; ----- Verzeichnispfad oder Verzeichnispfad mit Dateiname

Path = "C:\" 

; ----- Puffergröße für Security Descriptor ermitteln

GetFileSecurity_(@Path, #OWNER_SECURITY_INFORMATION, 0, 0, @SecurityDescriptorBufferSize)

If SecurityDescriptorBufferSize = 0
  MessageRequester("Fehler", "1.GetFileSecurity()-Aufruf: " + GetLastError())
  End
EndIf

SecurityDescriptorBuffer = AllocateMemory(SecurityDescriptorBufferSize)

; ----- Security Descriptor für Ordner oder Datei erstellen lassen

If GetFileSecurity_(@Path, #OWNER_SECURITY_INFORMATION, @SecurityDescriptorBuffer, SecurityDescriptorBufferSize, @AdditionalBytesNeeded) = #False
  MessageRequester("Fehler", "2.GetFileSecurity()-Aufruf: " + GetLastError())
  End
EndIf

; ----- Security ID (SID) des Besitzers ermitteln

If GetSecurityDescriptorOwner_(@SecurityDescriptorBuffer, @SIDPointer, @SIDDefaultedPointer) = #False
  MessageRequester("Fehler", "GetSecurityDescriptorOwner()-Aufruf: " + GetLastError())
  End
EndIf

If IsValidSid_(SIDPointer) = #False
  MessageRequester("Fehler", "IsValidSid()-Aufruf: Die vom GetSecurityDescriptorOwner()-Aufruf erhaltene Security ID ist ungültig!")
  End
EndIf

; ----- Länge von Benutzerkennung und Domänenname ermitteln

LookupAccountSid_(#NULL$, SIDPointer, 0, @AccountNameSize, 0, @DomainNameSize, SIDType)

If AccountNameSize = 0
  MessageRequester("Fehler", "Fehler beim 1.LookupAccountSid()-Aufruf: Die Länge der Benutzerkennung ist ungültig!")
  End
EndIf

AccountName = Space(AccountNameSize + 1)
DomainName = Space(DomainNameSize + 1)

; ----- Benutzername und Domänenname ermitteln

If LookupAccountSid_(#Null, SIDPointer, @AccountName, @AccountNameSize, @DomainName, @DomainNameSize, @SIDType) = #False
  MessageRequester("Fehler", "2.LookupAccountSid()-Aufruf: " + GetLastError())
  End
EndIf

MessageRequester("Info", "Verzeichnis/Dateiname: " + Path + #CR$ + "Benutzerkennung: " + AccountName + #CR$ + "Domäne/Arbeitsgruppe: " + DomainName, #MB_ICONINFORMATION)

End
real
Beiträge: 468
Registriert: 05.10.2004 14:43

Beitrag von real »

Seltsam:
Wenn ich den Code OHNE Debugger ausführe meldet Windows einen Fehler "... hat ein Problem festgestellt und muss geschlossen werden" und schliesst das Programm. Wenn ich den Debugger aktiviere funktioniert's. Und wenn ich eine .exe erstelle bricht diese mit genanntem Fehler ab... :?
Benutzeravatar
Shardik
Beiträge: 746
Registriert: 25.01.2005 12:19

Beitrag von Shardik »

@real:
Danke für den Hinweis. Ich hatte es bisher noch nicht ohne Debugger versucht... :roll:

Ich bin dabei auf ein seltsames Phänomen gestoßen, das auf einen Fehler in PB 3.94 und PB 4 oder im Win-API deuten könnte:

Wenn ich mit GetFileSecurity() die nötige Puffergröße für den Security Descriptor anfordere, erhalte ich in Variable SecurityDescriptorBufferSize den Wert 36 zurück. Beim zweiten Aufruf von GetFileSecurity() zur Erstellung der Kopie des Security Descriptor wird in SecurityDescriptorBufferSize der Wert 20 zurückgegeben... :shock:

Die Analyse des DrWatson-Dumps zeigt, daß der Fehler bei der Heap-Auflösung auftritt. Zuerst habe ich gemerkt, daß ich den SecurityDescriptorBuffer nicht mit FreeMemory() wieder freigegeben habe. Aber auch das Hinzufügen von FreeMemory() behebt den Fehler nicht.

Ich habe das Problem umgangen, indem ich den Speicher für den Security Descriptor nicht mehr mit dem anscheinend problematischen AllocateMemory() anfordere, sondern für den Puffer eine mit Leerzeichen vorbelegte Zeichenkette in der richtigen Länge anlege...

Code: Alles auswählen

Procedure.S GetLastError() 
  ErrorBufferPointer.L 
  ErrorCode.L 
  ErrorText.S 
  
  ErrorCode = GetLastError_() 
  ferr = FormatMessage_(#FORMAT_MESSAGE_ALLOCATE_BUFFER | #FORMAT_MESSAGE_FROM_SYSTEM, 0 , ErrorCode, GetUserDefaultLangID_(), @ErrorBufferPointer, 0, 0) 
  If ErrorBufferPointer <> 0 
    ErrorText = PeekS(ErrorBufferPointer) 
    LocalFree_(ErrorBufferPointer) 
    ProcedureReturn RemoveString(ErrorText, #CRLF$) 
  EndIf 
EndProcedure 


#OWNER_SECURITY_INFORMATION = 1 

AccountName.S
AccountNameSize.L
BufferSize.L
DomainName.S
DomainNameSize.L
Path.S
SIDPointer.L
SIDDefaultedPointer.L
SIDType.L
SecurityDescriptorBuffer.S
SecurityDescriptorBufferSize.L

; ----- Verzeichnispfad oder Verzeichnispfad mit Dateiname 

Path = "C:\" 

; ----- Puffergröße für Security Descriptor ermitteln 

GetFileSecurity_(@Path, #OWNER_SECURITY_INFORMATION, 0, 0, @SecurityDescriptorBufferSize) 

If SecurityDescriptorBufferSize = 0 
  MessageRequester("Fehler", "1.GetFileSecurity()-Aufruf: " + GetLastError()) 
  End 
EndIf 

SecurityDescriptorBuffer = Space(SecurityDescriptorBufferSize)

; ----- Security Descriptor für Ordner oder Datei erstellen lassen 

If GetFileSecurity_(@Path, #OWNER_SECURITY_INFORMATION, @SecurityDescriptorBuffer, SecurityDescriptorBufferSize, @BufferSize) = #False 
  MessageRequester("Fehler", "2.GetFileSecurity()-Aufruf: " + GetLastError()) 
  End 
EndIf 

; ----- Security ID (SID) des Besitzers ermitteln 

If GetSecurityDescriptorOwner_(@SecurityDescriptorBuffer, @SIDPointer, @SIDDefaultedPointer) = #False 
  MessageRequester("Fehler", "GetSecurityDescriptorOwner()-Aufruf: " + GetLastError()) 
  End 
EndIf 

If IsValidSid_(SIDPointer) = #False 
  MessageRequester("Fehler", "IsValidSid()-Aufruf: Die vom GetSecurityDescriptorOwner()-Aufruf erhaltene Security ID ist ungültig!") 
  End 
EndIf 

; ----- Länge von Benutzerkennung und Domänenname ermitteln 

LookupAccountSid_(#NULL$, SIDPointer, 0, @AccountNameSize, 0, @DomainNameSize, SIDType) 

If AccountNameSize = 0 
  MessageRequester("Fehler", "Fehler beim 1.LookupAccountSid()-Aufruf: Die Länge der Benutzerkennung ist ungültig!") 
  End 
EndIf

AccountName = Space(AccountNameSize + 1) 
DomainName = Space(DomainNameSize + 1) 

; ----- Benutzername und Domänenname ermitteln 

If LookupAccountSid_(#Null, SIDPointer, @AccountName, @AccountNameSize, @DomainName, @DomainNameSize, @SIDType) = #False
  MessageRequester("Fehler", "2.LookupAccountSid()-Aufruf: " + GetLastError()) 
  End 
EndIf 

MessageRequester("Info", "Verzeichnis/Dateiname: " + Path + #CR$ + "Benutzerkennung: " + AccountName + #CR$ + "Domäne/Arbeitsgruppe: " + DomainName, #MB_ICONINFORMATION) 

End
Diese Version läuft in PB 3.94 und in PB 4 korrekt, sowohl mit als auch ohne Debugger.
Antworten