Page 1 sur 1

un peu de WMI

Publié : mer. 28/juil./2004 2:39
par hardy
Je m'intéresse un peu au WMI ces temps ci, et voici un code qui, en l'occurrence, produit des notifications à chaque fois qu'une clé de registre dans HKLM\software est créee/modifiée/effacée.

pas encore fini : dans le IWbemClassObject récupéré dans la notification, j'ai pas encore trouvé l'identification de la clé. J'espère qu'elle est quelquepart dans ce fatras (sinon, à quoi ça sert?!)
Tiens, qui se dévoue pour trouver ça? Moi, j'ai déjà pas mal donné pour mettre au point le bidule qui suit :

Code : Tout sélectionner


OpenLibrary(0,"oleaut32.dll")

Declare privilege(pid)
privilege(GetCurrentProcessId_()) ; un d'eux est nécessaire, je ne sais plus lequel...

; appel nécessaire une seule fois dans la session pour que le serveur 
;WMI envoie des notifications concernant les évènements concernant 
; le registre. Inutile à partir de Windows 2000 : chargé au démarrage.

;ShellExecute_(0,"open","mofcomp.exe","c:\windows\system32\wbem\regevent.mof",0,#SW_SHOW)
;Delay(2000)
; si le fichier regevent.mof n'existe pas le créer.
;Il est fourni dans la plateforme SDK (répertoire WMI)
 
; constantes diverses

#COINIT_MULTITHREAD=0
#RPC_C_AUTHN_LEVEL_CONNECT=2
#RPC_C_IMP_LEVEL_IDENTIFY=2
#EOAC_NONE=0
#RPC_C_AUTHN_WINNT=10
#RPC_C_AUTHZ_NONE=0
#RPC_C_AUTHN_LEVEL_CALL=3
#RPC_C_IMP_LEVEL_IMPERSONATE=3
#CLSCTX_INPROC_SERVER=1
#WBEM_S_NO_ERROR = 0

; ___________ Conversions de chaînes _________________________

Procedure.l ansi2bstr(ansi.s)
  size.l=MultiByteToWideChar_(#CP_ACP,0,ansi,-1,0,0)
  Dim unicode.w(size)
  MultiByteToWideChar_(#CP_ACP, 0, ansi, Len(ansi), unicode(), size)
  ProcedureReturn SysAllocString_(@unicode()) 
EndProcedure

Procedure bstr2string(bstr)
Shared result.s
  result.s=""
  pos=bstr
  While PeekW(pos)
  result=result+Chr(PeekW(pos))
  pos=pos+2
  Wend
  ProcedureReturn @result
EndProcedure

;_______________affichage IID_____________________________

Procedure guid(piid)
mem=AllocateMemory(100)
StringFromGUID2_(piid,mem,100)
Debug "IID="+PeekS(bstr2string(mem))
FreeMemory(mem)
EndProcedure

; __________________ création d'une interface (IWbemObjectSink) _____


Structure IID ; on peut en fait utiliser la structure GUID déjà définie
  Data1.l       
  Data2.w
  Data3.w
  Data4.b[8]
EndStructure 

; déclaration de l'interface

Interface sink
queryinterface(riid.l,ppv.l)
addref()
release()
indicate(count.l,parray.l)
setstatus(flags.l,hresult.l,bstr.l,pobj.l)
EndInterface

Structure sink_fonctions
queryinterface.l
addref.l
release.l
indicate.l
setstatus.l
EndStructure

Structure sink_struct
*table.sink_fonctions
count.l
EndStructure

Declare queryinterface(*self.sink_struct,*riid.IID,ppv.l)
Declare addref(*self.sink_struct)
Declare release(*self.sink_struct)
Declare indicate(*self.sink_struct,pcount.l,parray.l)
Declare setstatus(*self_sink_struct,flags.l,hresult.l,bstr.l,pobj.l)


Global tableau.sink_fonctions
tableau\queryinterface=@queryinterface()
tableau\addref=@addref()
tableau\release=@release()
tableau\indicate=@indicate()
tableau\setstatus=@setstatus()

sink.sink_struct
sink\table=tableau
osink.sink=@sink

osink\addref(); le compteur doit être initialisé à 1

;___________fonctions de l'interface_____________

Procedure queryinterface(*self.sink_struct,*riid.IID,ppv.l)
If CompareMemory(*riid,?IID_IUnknown,SizeOf(IID)) Or CompareMemory(*riid,?IID_IWbemObjectSink,SizeOf(IID))
PokeL(ppv,*self)
*self\count+1
ProcedureReturn #S_OK
Else
PokeL(ppv,0)
ProcedureReturn #E_NOINTERFACE
EndIf
EndProcedure

Procedure addref(*self.sink_struct)
*self\count+1
ProcedureReturn *self\count
EndProcedure

Procedure release(*self.sink_struct)
*self\count-1
If *self\count=0
Debug "DELETE"
*self=0
ProcedureReturn 0
EndIf

ProcedureReturn *self\count
EndProcedure

Procedure indicate(*self.sink_struct,pcount.l,parray.l)
Debug "________________________________________"
Debug "Notification de "+Str(pcount)+" évènement(s)"
Debug "________________________________________"
;For i=0 To pcount-1
Debug "évènement "+Str(i+1)
event.IWbemClassObject=PeekL(parray+4*i)
event\GetObjectText(0,@bstr)
If bstr : Debug "Texte="+PeekS(bstr2string(bstr))
SysFreeString_(bstr)
EndIf

mem=AllocateMemory(1000)

event\getnames(0,0,0,@parray)
CallFunction(0,"SafeArrayGetUBound",parray,1,@ubound)
For pos=0 To ubound
CallFunction(0,"SafeArrayGetElement",parray,@pos,@elem)
hres=event\get(elem,0,mem,0,0)
type=PeekW(mem)
Select type
Case 8
val.s=PeekS(bstr2string(PeekL(mem+8)))
Case 3
val.s=Str(PeekL(mem+8))
Default
val.s=""
EndSelect
VariantClear_(mem)
event\getpropertyorigin(elem,@origin)

Debug "propriété="+PeekS(bstr2string(elem))+" type="+Hex(type)+" valeur="+val+" origine="+PeekS(bstr2string(origin))
SysFreeString_(elem)
SysFreeString_(origin)
Next


;next
FreeMemory(mem)


Debug "Fin de notification"
ProcedureReturn #WBEM_S_NO_ERROR
EndProcedure

Procedure setstatus(*self_sink_struct,flags.l,hresult.l,bstr.l,pobj.l)
ProcedureReturn 0
EndProcedure



; ___________________ Initialisations __________________________

; partout, hres doit être nul si pas d'erreur

hres=CoInitializeEx_(0,#COINIT_MULTITHREAD)
hres=CoInitializeSecurity_(0, -1,0,0,#RPC_C_AUTHN_LEVEL_CONNECT,#RPC_C_IMP_LEVEL_IDENTIFY,0,#EOAC_NONE,0)

loc.IWbemLocator

; __________________ Initialisation de loc ____________________

hres=CoCreateInstance_(?CLSID_WbemLocator,0,#CLSCTX_INPROC_SERVER,?IID_IWbemLocator,@loc)


svc.IWbemServices
; __________________________ Initialisation de svc ________________

hres=loc\ConnectServer(ansi2bstr("root\default"),0,0,0,0,0,0,@svc)
; A partir de là, l'interface svc est utilisable

hres=CoSetProxyBlanket_(svc,#RPC_C_AUTHN_WINNT,#RPC_C_AUTHZ_NONE,0,#RPC_C_AUTHN_LEVEL_CALL,#RPC_C_IMP_LEVEL_IMPERSONATE,0,#EOAC_NONE)

hres=svc\ExecNotificationQueryAsync(ansi2bstr("WQL"),ansi2bstr("SELECT * FROM RegistryTreeChangeevent WHERE Hive='HKEY_LOCAL_MACHINE' AND RootPath='Software'"),$80,0,osink)


;_________________ test______________________

For i=1 To 3
  If RegCreateKeyEx_(#HKEY_LOCAL_MACHINE, "Software\Microsoft\Windows\CurrentVersion\Run", 0, 0, #REG_OPTION_NON_VOLATILE, #KEY_ALL_ACCESS, 0, @NewKey, @KeyInfo) = #ERROR_SUCCESS 
  StringBuffer.s =Chr(65+i)
  RegSetValueEx_(NewKey, "Test", 0, #REG_SZ,@StringBuffer, Len(StringBuffer)+1) 
  RegCloseKey_(NewKey) 
  Delay(30)
  EndIf
 
Next


Delay(10000)

Debug "ARRET"

CloseLibrary(0)
svc\CancelAsyncCall(osink)
osink\release()
svc\release()
loc\release()
CoUninitialize_()
End

;_______________ données_________________________

DataSection
CLSID_WbemLocator:
    ;4590f811-1d3a-11d0-891f-00aa004b2e24
      Data.l $4590f811
      Data.w $1d3a, $11d0
      Data.b $89, $1f, $00, $aa, $00, $4b, $2e, $24
IID_IWbemLocator:
    ;dc12a687-737f-11cf-884d-00aa004b2e24
      Data.l $dc12a687
      Data.w $737f, $11cf
      Data.b $88, $4d, $00, $aa, $00, $4b, $2e, $24
IID_IUnknown: 
    ;00000000-0000-0000-C000-000000000046
    Data.l $00000000
    Data.w $0000, $0000
    Data.b $C0, $00, $00, $00, $00, $00, $00, $46 
IID_IWbemObjectSink:
    ;7C857801-7381-11CF-884D-00AA004B2E24
    Data.l $7C857801
    Data.w $7381, $11CF
    Data.b $88,$4D,$00,$AA,$00,$4B,$2E,$24

EndDataSection

;_________________acquisition des privilèges_________

Procedure privilege(pid)

ph=OpenProcess_($1F0FFF,1,pid)
OpenProcessToken_(ph,$20,@h)

Dim p.s(29)
p(0)="SeAssignPrimaryTokenPrivilege"
p(1)="SeAuditPrivilege"
p(2)="SeBackupPrivilege"
p(3)="SeChangeNotifyPrivilege"
p(4)="SeCreateGlobalPrivilege"
p(5)="SeCreatePagefilePrivilege"
p(6)="SeCreatePermanentPrivilege"
p(7)="SeCreateTokenPrivilege"
p(8)="SeDebugPrivilege"
p(9)="SeEnableDelegationPrivilege"
p(10)="SeImpersonatePrivilege"
p(11)="SeIncreaseBasePriorityPrivilege"
p(12)="SeIncreaseQuotaPrivilege"
p(13)="SeLoadDriverPrivilege"
p(14)="SeLockMemoryPrivilege"
p(15)="SeMachineAccountPrivilege"
p(16)="SeManageVolumePrivilege"
p(17)="SeProfileSingleProcessPrivilege"
p(18)="SeRemoteShutdownPrivilege"
p(19)="SeRestorePrivilege"
p(20)="SeSecurityPrivilege"
p(21)="SeShutdownPrivilege"
p(22)="SeSyncAgentPrivilege"
p(23)="SeSystemEnvironment"
p(24)="SeSystemProfilePrivilege"
p(25)="SeSystemtimePrivilege"
p(26)="SeTakeOwnershipPrivilege"
p(27)="SeTcbPrivilege"
p(28)="SeUndockPrivilege"
p(29)="SeUnsolicitedInputPrivilege"

Structure LI
low.l
high.l
EndStructure

Structure luidandattributes
pluid.LI
attrib.l
EndStructure

Structure privileges
count.l
privilege.luidandattributes
EndStructure

shut.LI
result=1
For i=0 To 29
LookupPrivilegeValue_(0,@p(i),@shut)

newprivilege.privileges
newprivilege\count=1
newprivilege\privilege\attrib=2
newprivilege\privilege\pluid\low=shut\low
newprivilege\privilege\pluid\high=shut\high

result=result*AdjustTokenPrivileges_(h,0,newprivilege,SizeOf(privileges),0,0)
Next i

ProcedureReturn result
EndProcedure