jazzyjeff

CredWrite API

17 posts in this topic

Hello,

I need my program to be able to add credentials in Credential manager in Windows 7. I have used the "net use x: \\servername\sharename /savecred' Command, but it doesn't seem very clean and I am not always guaranteed that it works as sometimes CMD hangs.

I see there is an API to add credentials on the MSDN site called CredWrite. I have made my best attempt to get this to work, but I am not having much luck.

I am hoping someone can look at my code and help point me in the right direction.

Here is the code I have for a UDF function:

Func _WinAPI_CredWrite($credential[11],$credential[6],$credential[2])
$credential[0] = 4 ;Flags
$credential[1] = 2 ;Type
$credential[2] = "" ;TargetName - Servername
$credential[3] = "" ;Comment
$credential[4] = @HOUR & ":" & @MIN ;LastWritten
$credential[5] = 512 ;CredentialBlobSize
$credential[6] = "" ;CredentialBlob - Password?
$credential[7] = 2 ;Persist
$credential[8] = 64 ;AttributeCount
$credential[9] = "" ; Attributes
$credential[10] = "" ;TargetAlias
$credential[11] = "" ;Username
Local $Ret = DllCall('advapi32.dll', 'int', 'CredWriteW', 'ptr', $credential, 'dword', 0)
EndFunc   ;==>_WinAPI_CredWrite

The URL for the API function is:

http://msdn.microsoft.com/en-us/library/aa375187(v=VS.85).aspx

Thanks for any help!

Jeff

Share this post


Link to post
Share on other sites



You need to use a dllstruct, not an array... i formatted the struct for ya:

#cs
typedef struct _CREDENTIAL {
  DWORD              Flags;
  DWORD              Type;
  LPTSTR                TargetName;
  LPTSTR                Comment;
  FILETIME            LastWritten;
  DWORD              CredentialBlobSize;
  LPBYTE                CredentialBlob;
  DWORD              Persist;
  DWORD              AttributeCount;
  PCREDENTIAL_ATTRIBUTE Attributes;
  LPTSTR                TargetAlias;
  LPTSTR                UserName;
} CREDENTIAL, *PCREDENTIAL;

typedef struct _CREDENTIAL_ATTRIBUTE {
  LPTSTR Keyword;
  DWORD  Flags;
  DWORD  ValueSize;
  LPBYTE Value;
} CREDENTIAL_ATTRIBUTE, *PCREDENTIAL_ATTRIBUTE;
#ce
$tagFILETIME =  "DWORD lowpart;DWORD highpart;"
   
$tagCREDENTIAL_ATTRIBUTE =  "wchar* Keyword;DWORD Flags; DWORD ValueSize; byte* Value;"
$tagCREDENTIAL= "" & _
    "DWORD Flags;" & _
    "DWORD Type;"  & _
    "wchar* TargetName;" & _
    "wchar* Comment;" & _
    $tagFILETIME & _
    "DWORD CredintialBlobSize" & _
    "byte* CredentialBlob" & _
    "DWORD Persist;" & _
    "DWORD AttributeCount;" & _
    "ptr Attributes;" & _ ; CREDENTIAL_ATTRIBUTE * Attributes, that is, array of those
    "wchar* TargetAlias;" &_
    "wchar* Username;"

Set data like this:

$Cred = DllStructCreate($tagCREDENTIAL)
DllStructSetData($Cred,"Flags",0x04);

Anything called "ptr" or has an asterisk needs a seperate dllstruct since they themselves are pointers to other structs.. following me? :graduated:


Ever wanted to call functions in another process? ProcessCall UDFConsole stuff: Console UDFC Preprocessor for AutoIt OMG

Share this post


Link to post
Share on other sites

Thanks for your response Shaggi. I feel like I understand what you are saying and then I read through the help file to learn about the DLLStructs and I feel more confident about using those. However, I still don't know how you implement the DLLStruct with the DLLCall.

Here is what I now have with your help.

$tagFILETIME =  "DWORD lowpart;DWORD highpart;"
$tagCREDENTIAL_ATTRIBUTE =  "wchar* Keyword;DWORD Flags; DWORD ValueSize; byte* Value;"
$tagCREDENTIAL= "" & _
    "DWORD Flags;" & _
    "DWORD Type;"  & _
    "wchar* TargetName;" & _
    "wchar* Comment;" & _
    $tagFILETIME & _
    "DWORD CredintialBlobSize" & _
    "byte* CredentialBlob" & _
    "DWORD Persist;" & _
    "DWORD AttributeCount;" & _
    "ptr Attributes;" & _ ; CREDENTIAL_ATTRIBUTE * Attributes, that is, array of those
    "wchar* TargetAlias;" & _
    "wchar* Username;"
$Cred = DllStructCreate($tagCREDENTIAL)
DllStructSetData($Cred,"Flags",0x04);
DllStructSetData($Cred,"Type",0x02);
DllStructSetData($Cred,"TargetName","\\servername");
DllStructSetData($Cred,"Comment","");
DllStructSetData($Cred,$tagFILETIME,@HOUR & ":" & @MIN);
DllStructSetData($Cred,"CredentialBlobSize",512);
DllStructSetData($Cred,"CredentialBlob","Password");
DllStructSetData($Cred,"Persist",0x02);
DllStructSetData($Cred,"AttributeCount",64);
DllStructSetData($Cred,"TargetAlias","Servername");
DllStructSetData($Cred,"Username","domain\username");
DllCall('advapi32.dll', 'int', 'CredWriteW', 'ptr', $cred, 'dword', 0)

I feel like once I have set the data in the DLL Struct, I then just run a DLLCall with the $cred variable. This doesn't seem to work though, so I am obviously missing something here.

Share this post


Link to post
Share on other sites

if it is asking for a ptr to a "credential structure", then you need to use dllstructgetptr().

DllCall('advapi32.dll', 'int', 'CredWriteW', 'ptr', DllStructGetPtr($cred), 'dword', 0)

Share this post


Link to post
Share on other sites

Thanks for your response Shaggi. I feel like I understand what you are saying and then I read through the help file to learn about the DLLStructs and I feel more confident about using those. However, I still don't know how you implement the DLLStruct with the DLLCall.

Here is what I now have with your help.

$tagFILETIME =  "DWORD lowpart;DWORD highpart;"
$tagCREDENTIAL_ATTRIBUTE =  "wchar* Keyword;DWORD Flags; DWORD ValueSize; byte* Value;"
$tagCREDENTIAL= "" & _
    "DWORD Flags;" & _
    "DWORD Type;"  & _
    "wchar* TargetName;" & _
    "wchar* Comment;" & _
    $tagFILETIME & _
    "DWORD CredintialBlobSize" & _
    "byte* CredentialBlob" & _
    "DWORD Persist;" & _
    "DWORD AttributeCount;" & _
    "ptr Attributes;" & _ ; CREDENTIAL_ATTRIBUTE * Attributes, that is, array of those
    "wchar* TargetAlias;" & _
    "wchar* Username;"
$Cred = DllStructCreate($tagCREDENTIAL)
DllStructSetData($Cred,"Flags",0x04);
DllStructSetData($Cred,"Type",0x02);
DllStructSetData($Cred,"TargetName","\\servername");
DllStructSetData($Cred,"Comment","");
DllStructSetData($Cred,$tagFILETIME,@HOUR & ":" & @MIN);
DllStructSetData($Cred,"CredentialBlobSize",512);
DllStructSetData($Cred,"CredentialBlob","Password");
DllStructSetData($Cred,"Persist",0x02);
DllStructSetData($Cred,"AttributeCount",64);
DllStructSetData($Cred,"TargetAlias","Servername");
DllStructSetData($Cred,"Username","domain\username");
DllCall('advapi32.dll', 'int', 'CredWriteW', 'ptr', $cred, 'dword', 0)

I feel like once I have set the data in the DLL Struct, I then just run a DLLCall with the $cred variable. This doesn't seem to work though, so I am obviously missing something here.

Do like beege said. However, there are some thing you still need to work on:

Anything called "ptr" or has an asterisk needs a seperate dllstruct since they themselves are pointers to other structs.. following me? :graduated:

What that really means is, that if you for example want to put a string in your struct, you need to make a new struct, put the data in that, and set the member in the old struct as the pointer to the new... It is done like this so it doesn't screw up the struct size. Example:

WRONG:

DllStructSetData($Cred,"TargetName","\\servername");

GOOD:

$TargetName = DllStructCreate("wchar[100]")
DllStructSetData($TargetName,1,"\\servername")
DllStructSetData($Cred,"TargetName",DllStructGetPtr($TargetName))

I know it seems a little tricky... But autoit wasn't really designed to do this kind of stuff painless. Nested structs makes it even worse. But youre on the right track!


Ever wanted to call functions in another process? ProcessCall UDFConsole stuff: Console UDFC Preprocessor for AutoIt OMG

Share this post


Link to post
Share on other sites

Thanks Beege and Shaggi.

I'm not ignoring your responses, I am just trying to figure everything you have told me out. I'll keep you posted on how I make out.

Thanks for all your help.

Share this post


Link to post
Share on other sites

You guys have been great help and I feel like I am learning a lot about this... just not enough to get it working.

So I have been reading the help file more about DLLStructs, and so I figured I would try output the values to the Console.

$tagFILETIME =  "DWORD lowpart;DWORD highpart;"
$tagCREDENTIAL_ATTRIBUTE =  "wchar* Keyword;DWORD Flags; DWORD ValueSize; byte* Value;"
$tagCREDENTIAL= "" & _
    "DWORD Flags;" & _
    "DWORD Type;"  & _
    "wchar* TargetName;" & _
    "wchar* Comment;" & _
    $tagFILETIME & _
    "DWORD CredintialBlobSize;" & _
    "byte* CredentialBlob;" & _
    "DWORD Persist;" & _
    "DWORD AttributeCount;" & _
    "ptr Attributes;" & _ ; CREDENTIAL_ATTRIBUTE * Attributes, that is, array of those
    "wchar* TargetAlias;" & _
    "wchar* Username;"
$Cred = DllStructCreate($tagCREDENTIAL)
DllStructSetData($Cred,"Flags",0x04);
DllStructSetData($Cred,"Type",0x02);
DllStructSetData($Cred,"Persist",0x02);
DllStructSetData($Cred,"AttributeCount",64);
DllStructSetData($Cred,$tagFILETIME,@HOUR & ":" & @MIN);
DllStructSetData($Cred,"CredentialBlobSize",512);
$targetName = DllStructCreate("wchar[100]")
DllStructSetData($targetName,1,"[url="file://\\servername"]\\servername[/url]")
DllStructSetData($Cred, "TargetName",DllStructGetPtr($targetName))
$comment = DllStructCreate("wchar[100]")
DllStructSetData($comment,1,"Comment")
DllStructSetData($Cred,"Comment",DllStructGetPtr($targetName))
$credentialBlob = DllStructCreate("byte[100]")
DllStructSetData($credentialBlob,1,"Password")
DllStructSetData($Cred,"CredentialBlob",DllStructGetPtr($credentialBlob));
$targetAlias = DllStructCreate("wchar[100]")
DllStructSetData($targetAlias,1,"Server")
DllStructSetData($Cred,"TargetAlias",DllStructGetPtr($targetAlias));
$username = DllStructCreate("wchar[100]")
DllStructSetData($username,1,"domain\username")
DllStructSetData($Cred,"Username",DllStructGetPtr($username));
DllCall('advapi32.dll', 'int', 'CredWriteW', 'ptr', DllStructGetPtr($Cred), 'dword', 0)
$1 = DllStructGetData($Cred,"Flags")
$2 = DllStructGetData($Cred,"Type")
$3 = DllStructGetData($Cred,"TargetName")
$4 = DllStructGetData($Cred,"Comment")
$5 = DllStructGetData($Cred, $tagFILETIME)
$6 = DllStructGetData($Cred,"CredentialBlobSize")
$7 = DllStructGetData($Cred,"CredentialBlob")
$8 = DllStructGetData($Cred,"Persist")
$9 = DllStructGetData($Cred,"AttributeCount")
$10 = DllStructGetData($Cred,"TargetAlias")
$11 = DllStructGetData($Cred,"Username")
ConsoleWrite(@CRLF & $1 & @CRLF & $2 & @CRLF & $3 & @CRLF & $4 & @CRLF & $5 & @CRLF & $6 & @CRLF & $7 & @CRLF & $8 & @CRLF & $9 & @CRLF & $10 & @CRLF & $11 & @CRLF)

All the values come to 0, so I am sure I am not obtaining the data properly from the DLLStruct.

So your example said to create a new DLLStruct when there is a string(?). Do you also have to do that for hex and decimal values? I did try on one and it didn't make a difference.

I'll explain how I am reading this and then perhaps you can tell me how I am looking at this all wrong.

We first create 2 variables:

$tagFILETIME - I have no idea really what information we are trying to get here.

$tagCredential_Attribute - Here we are telling the DLLStruct Types how to interpret the data. i.e. wchar* is a string/keyword.

$tagCredential - As required by the API we obtain/assign data that is used/required by the function in the DLL. i.e.TargetName, Username etc.

We then create the DLLStruct with the values in $tagCredential. We then are required to set the data/values for each attribute set in the DLLStruct. I.e. set the value of "Flags" to 0x04.

Now I create a new struct for the Attributes in $tagCredential and point the new struct back to the $cred struct.

Once I have repeated this for the other structs with string values, I then call the DLL with the function and point it to the variable of the first struct I created.

If you can offer anymore advice. Sorry for sounding a dumb ass, but as much as it may seem that I am not following along, I do feel like I am learning here! :-)

Share this post


Link to post
Share on other sites

Hello,

So I think I have a better understanding of why $tagCredential is there. I found the MSDN notes on the "Attributes" part of the DLLStruct and I realise the point of the array as mentioned in the notes.

So I now have that implemented in the script. I am still not able to ouptut values to the console that I have specified though.

Looking at how Yashied codes his API's I see that he seems to call the DLL first. I have tried this, but that doesn't make a difference to the result I get.

If I could get some more help in understanding this, that would be great.

Thanks,

Jeff

Global $attributes,$comment,$Cred,$credentialBlob,$tagCREDENTIAL,$tagCREDENTIAL_ATTRIBUTE,$tagFILETIME,$targetAlias,$targetName,$username
DllCall('advapi32.dll', 'int', 'CredWriteW', 'ptr', DllStructGetPtr($Cred), 'dword', 0)
$tagFILETIME =  "DWORD lowpart;DWORD highpart;"
$tagCREDENTIAL_ATTRIBUTE =  "wchar* Keyword;DWORD Flags; DWORD ValueSize; byte* Value;"
$tagCREDENTIAL= "" & _
    "DWORD Flags;" & _
    "DWORD Type;"  & _
    "wchar* TargetName;" & _
    "wchar* Comment;" & _
    $tagFILETIME & _
    "DWORD CredintialBlobSize;" & _
    "byte* CredentialBlob;" & _
    "DWORD Persist;" & _
    "DWORD AttributeCount;" & _
    "ptr Attributes;" & _ ; CREDENTIAL_ATTRIBUTE * Attributes, that is, array of those
    "wchar* TargetAlias;" & _
    "wchar* Username;"
$Cred = DllStructCreate($tagCREDENTIAL)
DllStructSetData($Cred,"Flags",0x04);
DllStructSetData($Cred,"Type",0x02);
DllStructSetData($Cred,"Persist",0x02);
DllStructSetData($Cred,"AttributeCount",0);
DllStructSetData($Cred,$tagFILETIME,@HOUR & ":" & @MIN);
DllStructSetData($Cred,"CredentialBlobSize",512);
$attributes = DllStructCreate($tagCREDENTIAL_ATTRIBUTE)
DllStructSetData($attributes,1,"")
DllStructSetData($Cred, "Keyword",DllStructGetPtr($attributes))
$attributes = DllStructCreate($tagCREDENTIAL_ATTRIBUTE)
DllStructSetData($attributes,2,0)
DllStructSetData($Cred, "Flags",DllStructGetPtr($attributes))
$attributes = DllStructCreate($tagCREDENTIAL_ATTRIBUTE)
DllStructSetData($attributes,3,256)
DllStructSetData($Cred, "ValueSize",DllStructGetPtr($attributes))
$attributes = DllStructCreate($tagCREDENTIAL_ATTRIBUTE)
DllStructSetData($attributes,4,"")
DllStructSetData($Cred, "Value",DllStructGetPtr($attributes))
$targetName = DllStructCreate("wchar[100]")
DllStructSetData($targetName,1,"\\servername")
DllStructSetData($Cred, "TargetName",DllStructGetPtr($targetName))
$comment = DllStructCreate("wchar[100]")
DllStructSetData($comment,1,"Comment")
DllStructSetData($Cred,"Comment",DllStructGetPtr($targetName))
$credentialBlob = DllStructCreate("byte[100]")
DllStructSetData($credentialBlob,1,"Password")
DllStructSetData($Cred,"CredentialBlob",DllStructGetPtr($credentialBlob));
$targetAlias = DllStructCreate("wchar[100]")
DllStructSetData($targetAlias,1,"Server")
DllStructSetData($Cred,"TargetAlias",DllStructGetPtr($targetAlias));
$username = DllStructCreate("wchar[100]")
DllStructSetData($username,1,"domain\username")
DllStructSetData($Cred,"Username",DllStructGetPtr($username));
$1 = DllStructGetData($Cred,"Flags")
$2 = DllStructGetData($Cred,"Type")
$3 = DllStructGetData($Cred,"TargetName")
$4 = DllStructGetData($Cred,"Comment")
$5 = DllStructGetData($Cred, $tagFILETIME)
$6 = DllStructGetData($Cred,"CredentialBlobSize")
$7 = DllStructGetData($Cred,"CredentialBlob")
$8 = DllStructGetData($Cred,"Persist")
$9 = DllStructGetData($Cred,"AttributeCount")
$10 = DllStructGetData($Cred,"Attributes",1)
$11 = DllStructGetData($Cred,"Attributes",2)
$12 = DllStructGetData($Cred,"Attributes",3)
$13 = DllStructGetData($Cred,"Attributes",4)
$14 = DllStructGetData($Cred,"TargetAlias")
$15 = DllStructGetData($Cred,"Username")
ConsoleWrite(@CRLF & $1 & @CRLF & $2 & @CRLF & $3 & @CRLF & $4 & @CRLF & $5 & @CRLF & $6 & @CRLF & $7 & @CRLF & $8 & @CRLF & $9 & @CRLF & $10 & @CRLF & $11 & @CRLF & $12 & @CRLF & $13 & @CRLF & $14 & @CRLF & $15 & @CRLF)

Share this post


Link to post
Share on other sites

#10 ·  Posted (edited)

Too sad, that not the final code was posted.

Here is my code.

For Domain Credentials: DllStructSetData($NewCred,"Type",2) 

For Generic change:  DllStructSetData($NewCred,"Type",1)   

 
 

 

 
 
Global $Target =  "MeinServer"
Global $User = "MeineDomainMeinUser" 
Global $Password = "MeinPWD"
Global $Comm = "mein Kommentar"
 
Global $Comment = DllStructCreate("wchar[100]")
DllStructSetData($Comment,1,$Comm)
 
Global $targetName = DllStructCreate("wchar[100]")
DllStructSetData($targetName,1,$Target)
 
Global $userName = DllStructCreate("wchar[100]")
DllStructSetData($userName,1,$User)
 
Global $credentialBlob = DllStructCreate("wchar[100]")
DllStructSetData($credentialBlob,1,$Password)
 
 
Global $structCREDENTIAL= "" & _
    "DWORD Flags;" & _
    "DWORD Type;"  & _
    "Ptr TargetName;" & _
    "Ptr Comment;" & _
    "UINT64 LastWritten;" & _
    "DWORD CredintialBlobSize;" & _
    "Ptr CredentialBlob;" & _
    "DWORD Persist;" & _
    "DWORD AttributeCount;" & _
    "ptr Attributes;" & _ 
    "Ptr TargetAlias;" & _
    "Ptr Username"
 
 
Global $NewCred = DllStructCreate($structCREDENTIAL)
If @error Then
MsgBox(0, "NewCred", "Error in DllStructCreate " & @error);
Exit
EndIf
 
 DllStructSetData($NewCred,"Flags",0)   
 DllStructSetData($NewCred,"Type",2)   
 DllStructSetData($NewCred,"TargetName",DllStructGetPtr($targetName))   
 DllStructSetData($NewCred,"Persist",3)
 DllStructSetData($NewCred,"AttributeCount",0) 
 DllStructSetData($NewCred,"UserName",DllStructGetPtr($userName))
 DllStructSetData($NewCred,"CredentialBlob",DllStructGetPtr($credentialBlob)) 
 DllStructSetData($NewCred,"CredintialBlobSize",StringLen($Password)*2)
 DllStructSetData($NewCred,"Comment",DllStructGetPtr($Comment))
 
#comments-start
MsgBox(0, "DllStruct", "Data:" & @CRLF & _
        "Flags: " & DllStructGetData($NewCred, "Flags") & @CRLF & _
"Type: " & DllStructGetData($NewCred,"Type") & @CRLF & _   
"TargetName: " &  DllStructGetData($NewCred,"TargetName") & @CRLF & _   
"Persist: " & DllStructGetData($NewCred,"Persist") & @CRLF & _
"AttributeCount: " &  DllStructGetData($NewCred,"AttributeCount") & @CRLF & _ 
"UserName: " &  DllStructGetData($NewCred,"UserName") & @CRLF & _
"CredentialBlob: " &  DllStructGetData($NewCred,"CredentialBlob") & @CRLF & _ 
"CredintialBlobSize: " &  DllStructGetData($NewCred,"CredintialBlobSize") & @CRLF & _
"Comment: " &  DllStructGetData($NewCred,"Comment"))
#comments-end
 
Local $hAdvapi32 = DllOpen("Advapi32.dll")
If @error Then 
Msgbox (0,"Error","Cannot open Advapi32.dll")
Exit
Endif
$Ret = DllCall($hAdvapi32, 'bool', 'CredWriteW', 'ptr', DllStructGetPtr($NewCred), 'dword', 0)
 
$NewCred = 0
Edited by KarlEm

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

I was able to use that code to do CredWrite successfully and even got CredDelete to work, but I can't get CredRead to work.

You can see the entry written appear in windows control panel->credential manager.

Here is what I have so far:

#include <array.au3>

;~ CredWrite("MeinServer", "MeineDomain\MeinUser", "MeinPWD", "mein Kommentar")
;~ CredDelete("MeinServer")

CredRead("MeinServer")

Func CredRead($Target)
    Local $targetName = DllStructCreate("wchar[100]")
    DllStructSetData($targetName,1,$Target)
    Local $Comment = DllStructCreate("wchar[100]")
    Local $userName = DllStructCreate("wchar[100]")
    Local $credentialBlob = DllStructCreate("wchar[100]")
    Local $structCREDENTIAL= "" & _
        "DWORD Flags;" & _
        "DWORD Type;"  & _
        "Ptr TargetName;" & _
        "Ptr Comment;" & _
        "UINT64 LastWritten;" & _
        "DWORD CredintialBlobSize;" & _
        "Ptr CredentialBlob;" & _
        "DWORD Persist;" & _
        "DWORD AttributeCount;" & _
        "ptr Attributes;" & _
        "Ptr TargetAlias;" & _
        "Ptr Username"
    Local $OutCred = DllStructCreate($structCREDENTIAL)
    DllStructSetData($OutCred,"TargetName",DllStructGetPtr($targetName))
    DllStructSetData($OutCred,"UserName",DllStructGetPtr($userName))
    DllStructSetData($OutCred,"CredentialBlob",DllStructGetPtr($credentialBlob))
    DllStructSetData($OutCred,"Comment",DllStructGetPtr($Comment))

    Local $hAdvapi32 = DllOpen("Advapi32.dll")
    $Ret = DllCall($hAdvapi32, 'bool', 'CredReadW', 'ptr', DllStructGetPtr($targetName), 'dword', 1, 'dword', 0, 'ptr', DllStructGetPtr($OutCred))
    _ArrayDisplay($Ret)
    $user = DllStructGetData($userName, 1)
    ConsoleWrite( $user & @CR)
    Return $user
EndFunc


func CredDelete($Target)
    Local $targetName = DllStructCreate("wchar[100]")
    DllStructSetData($targetName,1,$Target)

    Local $hAdvapi32 = DllOpen("Advapi32.dll")
    $Ret = DllCall($hAdvapi32, 'bool', 'CredDeleteW', 'ptr', DllStructGetPtr($targetName), 'dword', 1, 'dword', 0)
EndFunc

Func CredWrite($Target, $User, $Password, $Comm)
    Local $targetName = DllStructCreate("wchar[100]")
    DllStructSetData($targetName,1,$Target)

    Local $userName = DllStructCreate("wchar[100]")
    DllStructSetData($userName,1,$User)

    Local $credentialBlob = DllStructCreate("wchar[100]")
    DllStructSetData($credentialBlob,1,$Password)

    Local $Comment = DllStructCreate("wchar[100]")
    DllStructSetData($Comment,1,$Comm)

    Local $structCREDENTIAL= "" & _
        "DWORD Flags;" & _
        "DWORD Type;"  & _
        "Ptr TargetName;" & _
        "Ptr Comment;" & _
        "UINT64 LastWritten;" & _
        "DWORD CredintialBlobSize;" & _
        "Ptr CredentialBlob;" & _
        "DWORD Persist;" & _
        "DWORD AttributeCount;" & _
        "ptr Attributes;" & _
        "Ptr TargetAlias;" & _
        "Ptr Username"

    Local $NewCred = DllStructCreate($structCREDENTIAL)
    If @error Then
    MsgBox(0, "NewCred", "Error in DllStructCreate " & @error);
    Exit
    EndIf

    DllStructSetData($NewCred,"Flags",0)
    DllStructSetData($NewCred,"Type",1)
    DllStructSetData($NewCred,"TargetName",DllStructGetPtr($targetName))
    DllStructSetData($NewCred,"Persist",3)
    DllStructSetData($NewCred,"AttributeCount",0)
    DllStructSetData($NewCred,"UserName",DllStructGetPtr($userName))
    DllStructSetData($NewCred,"CredentialBlob",DllStructGetPtr($credentialBlob))
    DllStructSetData($NewCred,"CredintialBlobSize",StringLen($Password)*2)
    DllStructSetData($NewCred,"Comment",DllStructGetPtr($Comment))

    Local $hAdvapi32 = DllOpen("Advapi32.dll")
    If @error Then
    Msgbox (0,"Error","Cannot open Advapi32.dll")
    Exit
    Endif
    $Ret = DllCall($hAdvapi32, 'bool', 'CredWriteW', 'ptr', DllStructGetPtr($NewCred), 'dword', 0)
    $NewCred = 0
EndFunc

The DLL call to CredReadW will only return 1 if I call it with a Targetname for a credential that actually exists so I believe that it is working but I can't seem to get the data out of the output Credential struct. Or at least I think its a struct... For CredWrite MSDN says that the PCREDENTIAL parameter is pointer to a credential structure but for CredRead it says that PCREDENTIAL is a "Pointer to a single allocated block buffer to return the credential." Is this a pointer to a credential structure or something else? Does anyone know?

Either that or it is a pointer to a struct and I just can't get the data out. What is confusing me is that the credential structure has pointers to other structures/data types. What I did is create the other datatypes (like strings) and put their pointers into a credential structure and then pass the pointer of that credential structure to the CredRead function. I expected that the data I was interested in would be in the first data structures I made after the dll call was successful, but they contain nothing or a null string. Is this the correct way to do this?

Here is some code on stackoverflow that does credwrite and credread in C? or some other language.

Edited by garbb

Share this post


Link to post
Share on other sites

I really don't know why the structure has no the data(I just see a little bit), but if you do something like this can see that you want:

Func CredRead($Target)
    Local $targetName = DllStructCreate("wchar[100]")
    DllStructSetData($targetName,1,$Target)
    Local $Comment = DllStructCreate("wchar[100]")
    Local $userName = DllStructCreate("wchar[100]")
    Local $credentialBlob = DllStructCreate("wchar[100]")
    Local $structCREDENTIAL= "" & _
        "DWORD Flags;" & _
        "DWORD Type;"  & _
        "Ptr TargetName;" & _
        "Ptr Comment;" & _
        "UINT64 LastWritten;" & _
        "DWORD CredintialBlobSize;" & _
        "Ptr CredentialBlob;" & _
        "DWORD Persist;" & _
        "DWORD AttributeCount;" & _
        "ptr Attributes;" & _
        "Ptr TargetAlias;" & _
        "Ptr Username"
;~     Local $OutCred = DllStructCreate($structCREDENTIAL)
;~     DllStructSetData($OutCred,"TargetName",DllStructGetPtr($targetName))
;~     DllStructSetData($OutCred,"UserName",DllStructGetPtr($userName))
;~     DllStructSetData($OutCred,"CredentialBlob",DllStructGetPtr($credentialBlob))
;~     DllStructSetData($OutCred,"Comment",DllStructGetPtr($Comment))

    Local $hAdvapi32 = DllOpen("Advapi32.dll")
    $Ret = DllCall($hAdvapi32, 'bool', 'CredReadW', 'ptr', DllStructGetPtr($targetName), 'dword', 1, 'dword', 0, 'ptr*', 0)
    _ArrayDisplay($Ret)

Local $tdata=DllStructCreate("byte[200]",$Ret[4])



    FileWrite("data.txt",(DllStructGetData($tdata,1)))
    ShellExecute("data.txt")

    Return 0
EndFunc

Saludos

1 person likes this

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

Thank you!

I didn't realize that I could specify a ptr* as a parameter type or that I could create a struct and tell it to use a pointer. I finally made it work.

Here's the working CredRead function:

Func CredRead($Target)
    Local $FuncRet[3]

    Local $targetName = DllStructCreate("wchar[100]")
    DllStructSetData($targetName,1,$Target)

    Local $hAdvapi32 = DllOpen("Advapi32.dll")
    Local $Ret = DllCall($hAdvapi32, 'bool', 'CredReadW', 'ptr', DllStructGetPtr($targetName), 'dword', 1, 'dword', 0, 'ptr*', 0)

    if $ret[0]=0 then Return SetError(1,0,$FuncRet)

    Local $structCREDENTIAL= "" & _
        "DWORD Flags;" & _
        "DWORD Type;"  & _
        "Ptr TargetName;" & _
        "Ptr Comment;" & _
        "UINT64 LastWritten;" & _
        "DWORD CredintialBlobSize;" & _
        "Ptr CredentialBlob;" & _
        "DWORD Persist;" & _
        "DWORD AttributeCount;" & _
        "Ptr Attributes;" & _
        "Ptr TargetAlias;" & _
        "Ptr Username"

    Local $tdata=DllStructCreate($structCREDENTIAL, $Ret[4])

    Local $userName = DllStructCreate("wchar[100]", DllStructGetData($tdata, 'Username'))
    Local $User = DllStructGetData($userName, 1)

    Local $CredentialBlobSize = DllStructGetData($tdata, 'CredintialBlobSize')
    Local $credentialBlob = DllStructCreate("wchar[100]", DllStructGetData($tdata, 'CredentialBlob'))
    Local $Password = StringLeft(DllStructGetData($credentialBlob, 1), $CredentialBlobSize/2)

    Local $Comment = DllStructCreate("wchar[100]", DllStructGetData($tdata, 'Comment'))
    Local $Comm = DllStructGetData($Comment, 1)

    Dim $FuncRet[] = [$User, $Password, $Comm]
    Return $FuncRet
EndFunc 

It returns the username, password, and comment in an array.

Edited by garbb

Share this post


Link to post
Share on other sites

You're welcome. I did as you say first, but it did not work.(maybe I forget something.) :S

Saludos

Share this post


Link to post
Share on other sites

Hi @ all,

i need a function that read the Domain credentials.

As MSDN write's there is a difference in getting the result from the dllcall.

Generic Credentials are Read like this: http://msdn.microsoft.com/en-us/library/windows/desktop/ff714499(v=vs.85).aspx

Domain Credentials are read like that: http://msdn.microsoft.com/en-us/library/windows/desktop/ff714500(v=vs.85).aspx

The difference is, that in the output there is a double **, that means that there is a Ptr to a Ptr to an Array...

Plese help to get the above function from garbb working with domain Credentials.

Thank You all for Helping ^^

Schnuffel


The two basic principles of Windows system administration:
For minor problems, reboot -- For major problems, reinstall
"Sarkasm is the lowest form of humor, but the highest form of intelligenz"
Val McDermid

Share this post


Link to post
Share on other sites

It looks like a pointer to a pointer to an array of ENCRYPTED_CREDENTIALW structures and each one of those has as its first member a pointer to a CREDENTIAL structure which is the same as I was using in my credread() above to pull out the username and password:

Local $structCREDENTIAL= "" & .... etc

But then you may have a problem because it says on the MSDN page for the CREDENTIAL structure that

Also, for CRED_TYPE_DOMAIN_PASSWORD, this member can only be read by the authentication packages.

 

And if you google for more info about this you will find that:

Domain network password method uses more stricter technique for encrypting the credentials thus providing better security over other methods. Only system process, LSASS.EXE can encrypt or decrypt these kind of passwords. LSASS is a Windows core system process responsible for enforcing the security and executing various security oriented tasks. 
 
So in order to decrypt domain passwords one has to perform decryption in the context of LSASS process. This can be achieved by injecting remote thread into LSASS process using CreateRemoteThread function

 

And so I think in order to read stored domain passwords you must do a bit more hackery. There is other software that exists (of varying legitimacy) that will get you the information that you want...

...of course I am assuming that whatever you are trying to do is all for legitimate purposes...

Share this post


Link to post
Share on other sites

ty a lot garbb, as i don't want to "hack" the credentials i decided to go a different way without reading the domain cred's. I delete the Cred's that are in my interst and write them new with the user and Pass the user put in my Prog. I only wanted to check the cred's on a domain if they are locked or something like that. thx a lot Schnuffel


The two basic principles of Windows system administration:
For minor problems, reboot -- For major problems, reinstall
"Sarkasm is the lowest form of humor, but the highest form of intelligenz"
Val McDermid

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now

  • Similar Content

    • r0ash
      By r0ash
      Hey guys, MattDiesel over Stackoverflow mentioned this beautiful piece of code 
      #include <WindowsConstants.au3> #include <WinAPI.au3> Local $IDM_FONT = 33 Local $hWindow = WinGetHandle("Untitled - Notepad") _WinAPI_PostMessage($hWindow, $WM_COMMAND, $IDM_FONT, 0) Local $hFontWin = WinWait("Font") $select = ControlCommand($hFontWin, "", "ComboBox1", "GetCurrentSelection", "") WinClose($hFontWin) MsgBox(0,"", $select) I realized that _WinAPI_PostMessage can trigger menu click event, even if Notepad is minimized.
      How do we know what is the decimal value of *any menu item or sub-menu item*? How we know "Format > Font" menu-item is 33 as wParam to _WinAPI_PostMessage()? Have a look at snapshot.
      Regards.

    • chacoya121
      By chacoya121
      plz help explain between GDI+ and Winapi, is it desktop inside another desktop, 3 layer dimension?
      i can't get the picture
      1. u get desktop u can visual see
      2. then u create GDI+ startup another desktop screen dimension?
      3. then u have Winapi command inside GDI+, is this another desktop screen dimension? cuz GDI+ could create bitmap that is one dimension? Winapi get windowDC also another dimension?
      plz help and explain, with picture would be nice, im not good with visualize ("dumb newbie"), still learning
      newbie to programming world
      thankyou.
    • IErrors
      By IErrors
      I am working on some functionality to detect whether a standard keyboard was used for input in my UI or if a barcode scanner (that acts like a keyboard) was used. Instead of dealing with a scanner SDK, I decided I would read from the raw input to get device info and make a determination.
      I discovered while testing with multiple UIs is that when the WM_INPUT message is received and the function called, the $hWnd param is always the same (apparently whatever handle I set the "hTarget" to in the RAWINPUTDEVICE struct).
      Is this normal behavior??
      Using the test code below, no matter what window you give input to the $hWnd param never changes.
      #include <WindowsConstants.au3> #include <GUIConstantsEx.au3> #include <WinAPISys.au3> $Form1 = GUICreate("Form 1", 300, 300, -1, 10) ConsoleWrite("$Form1 = " & $Form1 & @CRLF) $Edit1 = GUICtrlCreateEdit("", 0, 0, 300, 300) GUISetState(@SW_SHOW, $Form1) $Form2 = GUICreate("Form 2", 300, 300, -1, 350) ConsoleWrite("$Form2 = " & $Form2 & @CRLF) $Edit2 = GUICtrlCreateEdit("", 0, 0, 300, 300) GUISetState(@SW_SHOW, $Form2) GUIRegisterMsg($WM_INPUT, "WM_INPUT") ; https://msdn.microsoft.com/en-us/library/ms645590(v=vs.85).aspx $tRID = DllStructCreate($tagRAWINPUTDEVICE) ; https://msdn.microsoft.com/en-us/library/ms645565(v=vs.85).aspx DllStructSetData($tRID, "UsagePage", 1) DllStructSetData($tRID, "Usage", 6) DllStructSetData($tRID, "Flags", 0) DllStructSetData($tRID, "hTarget", $Form1) ; According to the struct def, if hTarget=NULL then it should follow keyboard focus. - nope :( $pRID = DllStructGetPtr($tRID) _WinAPI_RegisterRawInputDevices($pRID) ; https://msdn.microsoft.com/en-us/library/ms645600(v=vs.85).aspx Do Until GUIGetMsg() = $GUI_EVENT_CLOSE Func WM_INPUT($hWnd, $iMsg, $wParam, $lParam) ConsoleWrite("hWnd = " & $hWnd & " | Title = " & WinGetTitle($hWnd) & @CRLF) ConsoleWrite("Active Window = " & WinGetTitle("[ACTIVE]") & @CRLF) Return $GUI_RUNDEFMSG EndFunc ;==>WM_INPUT  
    • Adrian123
      By Adrian123
      Hi I need help with the code bellow, my goal is to make faster sqlite queries to Sqlite because _SQLite_GetTable2d seams to be slow on big tables.
      Thank you :
       
      https://www.autoitscript.com/forum/topic/182469-using-controls-to-edit-cells-in-a-listview/
       
      Well my code is faster but a I have 2 issues :
      1 Memory leaks
      2 Listview ( virtual) a little slow when scrolling (column headers delay )
      Please help I am not a WinApi specialist. (The hugetable its actuality much bigger I'm limited by upload size)
      Thank You.
       
      #comments-start C++ Source of Dll #include <vector> #include <string> #include <stdio.h> #include <string.h> #include "sqlite3.h" using namespace std; extern "C" { // A function adding two integers and returning the result char * SqliteSelect(char * path ,char * sSql , char * rowsep, char * tabsep ) { std::string rez=""; bool once=true; sqlite3 *db; if ( sqlite3_open_v2(path, &db,SQLITE_OPEN_READONLY, NULL) == SQLITE_OK) { sqlite3_stmt *stmt; if (sqlite3_prepare_v2(db, sSql, -1, &stmt, 0) == SQLITE_OK) { int nCols = sqlite3_column_count(stmt); while (sqlite3_step(stmt) == SQLITE_ROW) { for (int nCol = 0; nCol < nCols; nCol++) { if (once==true) { rez+=(char *) sqlite3_column_name(stmt, nCol); if (nCol < nCols-1 ) { rez+=tabsep; } else { rez+=rowsep; once=false; // sqlite3_reset(stmt); nCol=0; } } if (once==false){ if ( sqlite3_column_text(stmt, nCol)!=nullptr) { rez+=(char *) sqlite3_column_text(stmt, nCol); } if (nCol < nCols-1 ) rez+=tabsep; } } rez+=rowsep; } } else { return (char *)sqlite3_errmsg(db); sqlite3_close(db); } sqlite3_close(db); } char *cstr = new char[rez.length() + 1]; strcpy(cstr, rez.c_str()); return cstr; } char * SqliteExec(char * path ,char * sSql ) { std::string rez="Error: "; sqlite3 *db; char *error; if ( sqlite3_open_v2(path, &db,SQLITE_OPEN_READWRITE, NULL) == SQLITE_OK) { sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL,&error); if( sqlite3_exec(db, sSql, NULL, NULL, &error) != SQLITE_OK ) { rez+= (char *)sqlite3_errmsg(db); sqlite3_exec(db, "ROLLBACK", NULL, NULL, &error); sqlite3_close(db); } sqlite3_exec(db, "END TRANSACTION", NULL, NULL, &error); sqlite3_close(db); if (rez=="Error: " ) { rez="OK"; } char *cstr = new char[rez.length() + 1]; strcpy(cstr, rez.c_str()); return cstr; } } } #comments-end #include <GuiListView.au3> #include <GUIConstantsEx.au3> #include <StaticConstants.au3> #include <WindowsConstants.au3> #include <WinAPIvkeysConstants.au3> #include <WinAPIShellEx.au3> #include <GuiEdit.au3> Opt( "MustDeclareVars", 1 ) Global $hListView, $iItem = -1, $iSubItem = 0, $aRect Global $idComboOpen, $idComboClose, $bComboOpen = False, $bComboDoNotOpen = False Global $bEditEscape = True, $bEditUpDown = False, $bListboxOpen = False Global $bComboOpenOnEnter = True Global $bComboOpenOnSpace = False Global $bComboOpenOnDoubleClick = True Global $bListboxAcceptClickEnter = True Global $hEdit ;Global $Table Func __SQLite_StringToUtf8Struct($sString) Local $aResult = DllCall("kernel32.dll", "int", "WideCharToMultiByte", "uint", 65001, "dword", 0, "wstr", $sString, "int", -1, _ "ptr", 0, "int", 0, "ptr", 0, "ptr", 0) If @error Then Return SetError(1, @error, "") ; DllCall error Local $tText = DllStructCreate("char[" & $aResult[0] & "]") $aResult = DllCall("kernel32.dll", "int", "WideCharToMultiByte", "uint", 65001, "dword", 0, "wstr", $sString, "int", -1, _ "struct*", $tText, "int", $aResult[0], "ptr", 0, "ptr", 0) If @error Then Return SetError(2, @error, "") ; DllCall error Return $tText EndFunc ;==>__SQLite_StringToUtf8Struct Global $Headers ,$RowsArray Global $TabSep =@TAB Example() Func Compare_Headers($ArrayIni,$Array_) If UBound($ArrayIni)<> UBound($Array_) Then Return 1 EndIf For $R=0 to UBound($ArrayIni)-1 if $ArrayIni[$R] <> $Array_[$R] Then Return 1 EndIf Next Return 0 EndFunc #include <File.au3> Func nCheckDB( $sDBname , $SSQL , $idListView ) Local $iniH =$Headers; GUICtrlSendMsg( $idListView, $LVM_SETITEMCOUNT,0, 0) Local $RowSep =@LF Local $tFilename = __SQLite_StringToUtf8Struct($sDBname) Local $tSsql = __SQLite_StringToUtf8Struct($SSQL ) Local $hDLL = DllOpen("libSlqiteFaster.dll") Local $Arrx = DllCall($hDLL,"STR" ,"SqliteSelect", "struct*", $tFilename ,"struct*" ,$tSsql ,"struct*" ,__SQLite_StringToUtf8Struct($RowSep) ,"struct*" ,__SQLite_StringToUtf8Struct($TabSep) ) DllClose($hDLL) $RowsArray= StringSplit($Arrx[0],$RowSep) $Headers=StringSplit($RowsArray[1],$TabSep) Local $iCols = $Headers[0] Local $iRows = $RowsArray[0] If Compare_Headers( $iniH,$Headers)=1 Then While _GUICtrlListView_GetColumnCount($idListView)>0 _GUICtrlListView_DeleteColumn ( $idListView, 0 ) WEnd For $i = 1 To $iCols _GUICtrlListView_AddColumn( $idListView,$Headers[ $i ], 75 ) Next EndIf GUICtrlSendMsg( $idListView, $LVM_SETITEMCOUNT, $iRows-2, 0 ) ;$RowsArray=0 ;$Headers=0 $iRows=0 $iCols=0 $tFilename=0 $tSsql=0 EndFunc Func Example() Local $hGui = GUICreate( "LV_", @DesktopWidth-20, @DesktopHeight-40,-1,-1, $WS_SIZEBOX+$WS_MAXIMIZEBOX+ $WS_MINIMIZEBOX ) Global $Button3 = GUICtrlCreateButton("Ne3", 400, 0, 75, 25) Global $Button1 = GUICtrlCreateButton("NeSmler", 100, 0, 75, 25) Local $idListView Local $pListViewCallback Local $pEditCallback Local $pListCommand Local $pGuiCallback ;MsgBox(0,"","STOP") $idListView= GUICtrlCreateListView( "", 10, 40, @DesktopWidth-20-20, @DesktopHeight-80-100,$LVS_OWNERDATA ) ;$LVS_NOCOLUMNHEADER _GUICtrlListView_SetExtendedListViewStyle( $idListView, BitOR($LVS_EX_FULLROWSELECT, $LVS_EX_BORDERSELECT,$LVS_EX_DOUBLEBUFFER, $LVS_EX_GRIDLINES) ) ; $LVS_EX_DOUBLEBUFFER+$LVS_EX_FULLROWSELECT + GUICtrlSetResizing($hGui, $GUI_DOCKBORDERS) $hListView = GUICtrlGetHandle( $idListView ) ; Subclass ListView to handle messages related to ComboBox ; ComboBox open and close events $idComboOpen = GUICtrlCreateDummy() $idComboClose = GUICtrlCreateDummy() GUIRegisterMsg( $WM_NOTIFY, "WM_NOTIFY" ) ; Subclass callback functions $pListViewCallback= DllCallbackGetPtr( DllCallbackRegister( "ListViewCallback", "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr" ) ) $pEditCallback = DllCallbackGetPtr( DllCallbackRegister( "EditCallback", "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr" ) ) $pListCommand = DllCallbackGetPtr( DllCallbackRegister( "ListCommand", "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr" ) ) $pGuiCallback = DllCallbackGetPtr( DllCallbackRegister( "GuiCallback", "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr" ) ) _WinAPI_SetWindowSubclass( $hListView, $pListViewCallback, 9998, 0 ) ; Show GUI GUISetState( @SW_SHOW ) ; Message loop While 1 Switch GUIGetMsg() Case $Button3 GuiSetState(@SW_LOCK, $hGui) nCheckDB("bigtable.sqlite" ,"SELECT * FROM hugetable;",$idListView ) GuiSetState(@SW_UNLOCK, $hGui) Case $Button1 GuiSetState(@SW_LOCK, $hGui) For $i = 0 To _GUICtrlListView_GetColumnCount($idListView)-1 _GUICtrlListView_SetColumnWidth ( $hListView, $i, $LVSCW_AUTOSIZE_USEHEADER ) ;$LVSCW_AUTOSIZE Next GuiSetState(@SW_UNLOCK, $hGui) #cs Local $S_PH = "C:\\Users\\achis\\Desktop\\PP2C 24.11.2015_OK\\Prod.sqlite" Local $SSQLi ="UPDATE sumbomLVL_Static Set part='10000611' WHERE rowid=1 ;" Local $hDLL = DllOpen("libSlqiteFaster.dll") Local $Arrx = DllCall($hDLL,"STR" ,"SqliteExec", "struct*", __SQLite_StringToUtf8Struct($S_PH) ,"struct*" ,__SQLite_StringToUtf8Struct($SSQLi) ) MsgBox ( 0,"",$Arrx[0]) DllClose($hDLL) #ce Case $idComboOpen If $bComboOpen Then ; If another ComboBox is open then delete it _WinAPI_RemoveWindowSubclass( $hEdit, $pEditCallback, 9999 ) ;_WinAPI_RemoveWindowSubclass( $hListView, $pListCommand, 9999 ) _WinAPI_RemoveWindowSubclass( $hGui, $pGuiCallback, 9999 ) _GUICtrlEdit_Destroy( $hEdit ) EndIf $hEdit = _GUICtrlEdit_Create( $hListView,_GUICtrlListView_GetItemText( $hListView, $iItem, $iSubItem ), $aRect[0], $aRect[1], $aRect[2] - $aRect[0],20,$ES_AUTOHSCROLL ) _GUICtrlEdit_SetSel( $hEdit, 0, -1 ) ; Create subclasses to handle Windows messages _WinAPI_SetWindowSubclass( $hEdit, $pEditCallback, 9999, 0 ) ; Messages from the Edit control of the ComboBox ;_WinAPI_SetWindowSubclass( $hListView, $pListCommand, 9999, 0 ) ; WM_COMMAND messages from Listbox part of ComboBox _WinAPI_SetWindowSubclass( $hGui, $pGuiCallback, 9999, 0 ) ; Handle GUI messages related to ComboBox control ; Set focus to ComboBox ; Subclasses are used only when ComboBox is open _WinAPI_SetFocus( $hEdit ) $bComboOpen = True Case $idComboClose If Not $bComboOpen Then ContinueLoop If GUICtrlRead( $idComboClose ) Then Local $c_item = StringSplit($RowsArray[$iItem+2],$TabSep)[$iSubItem+1] Local $T = StringSplit( $RowsArray[$iItem+2],$TabSep) $T[$iSubItem] =_GUICtrlEdit_GetText( $hEdit ) $RowsArray[$iItem+2]=_ArrayToString($T,$TabSep) _WinAPI_SetFocus( $hListView ) ; Set focus to ListView EndIf ; Delete ComboBox control _WinAPI_RemoveWindowSubclass( $hEdit, $pEditCallback, 9999 ) ;_WinAPI_RemoveWindowSubclass( $hListView, $pListCommand, 9999 ) _WinAPI_RemoveWindowSubclass( $hGui, $pGuiCallback, 9999 ) _GUICtrlEdit_Destroy( $hEdit ) $bComboOpen = False Case $GUI_EVENT_PRIMARYDOWN, $GUI_EVENT_SECONDARYDOWN If Not $bComboOpen Then ContinueLoop ; Clicks in Listbox part of ComboBox should not delete it If $bListboxOpen Then ContinueLoop ; Clicks in Edit part of ComboBox should not delete it Local $aPos = MouseGetWindowPos( $hListView ) If Not ( $aPos[0] > $aRect[0] And $aPos[0] < $aRect[2] And $aPos[1] > $aRect[1] And $aPos[1] < $aRect[1] + 20 ) Then GUICtrlSendToDummy( $idComboClose ) ; Delete ComboBox Local $aSize = WinGetPos( $hListView ) If $aPos[0] > 0 And $aPos[1] > 0 And $aPos[0] < $aSize[2] And $aPos[1] < $aSize[3] Then _ _WinAPI_SetFocus( $hListView ) ; Set focus to ListView if mouse click is inside ListView EndIf Case $GUI_EVENT_CLOSE Exit If Not $bEditEscape Then ExitLoop $bEditEscape = False EndSwitch WEnd ; Cleanup GUIDelete() EndFunc Func WM_NOTIFY( $hWnd, $iMsg, $wParam, $lParam ) Local Static $bNotXP = Not ( @OSVersion = "WIN_XP" ) Local Static $tRect = DllStructCreate( $tagRECT ) Local Static $hBrush = _WinAPI_CreateSolidBrush( 0xFFFF00 ) Local Static $tText = DllStructCreate( "wchar[50]" ) Local Static $pText = DllStructGetPtr( $tText ) Local $tNMHDR = DllStructCreate( $tagNMHDR, $lParam ) Local $hWndFrom = HWnd( DllStructGetData( $tNMHDR, "hWndFrom" ) ) Local $iCode = DllStructGetData( $tNMHDR, "Code" ) Switch $hWndFrom Case $hListView Switch $iCode Case $LVN_GETDISPINFOW Local $tNMLVDISPINFO = DllStructCreate( $tagNMLVDISPINFO, $lParam ) ; $LV_DISPINFO *lpdi = ($LV_DISPINFO *)$lParam; If BitAND( DllStructGetData( $tNMLVDISPINFO, "Mask" ), $LVIF_TEXT ) Then Local $iIndex = DllStructGetData( $tNMLVDISPINFO, "Item" ) Local $Subindex = DllStructGetData($tNMLVDISPINFO,"SubItem") Local $sItem = StringSplit($RowsArray[$iIndex+2],$TabSep)[$Subindex+1] ; $aResult[$iIndex][DllStructGetData($tNMLVDISPINFO,"SubItem")] DllStructSetData( $tText, 1, $sItem ) DllStructSetData( $tNMLVDISPINFO, "Text", $pText ) DllStructSetData( $tNMLVDISPINFO, "TextMax", StringLen( $sItem ) ) EndIf Case $NM_CUSTOMDRAW Local $tNMLVCustomDraw = DllStructCreate( $tagNMLVCUSTOMDRAW, $lParam ) Local $dwDrawStage = DllStructGetData( $tNMLVCustomDraw, "dwDrawStage" ) Switch $dwDrawStage ; Specifies the drawing stage ; Stage 1 Case $CDDS_PREPAINT ; Before the paint cycle begins Return $CDRF_NOTIFYITEMDRAW ; Stage 2 will be carried out ; Stage 2 Case $CDDS_ITEMPREPAINT ; Before an item is painted If Not _GUICtrlListView_GetItemState( $hListView, DllStructGetData( $tNMLVCUSTOMDRAW, "dwItemSpec" ), $LVIS_FOCUSED ) Then Return $CDRF_NEWFONT ; Default drawing of item $iItem = DllStructGetData( $tNMLVCUSTOMDRAW, "dwItemSpec" ) Return $CDRF_NOTIFYSUBITEMDRAW ; Stage 3 will be carried out ; Stage 3 Case BitOR( $CDDS_ITEMPREPAINT, $CDDS_SUBITEM ) ; Before a subitem is painted Return $CDRF_NOTIFYPOSTPAINT ; Stage 4 will be carried out ; Stage 4 Case BitOR( $CDDS_ITEMPOSTPAINT, $CDDS_SUBITEM ) ; After a subitem has been painted If DllStructGetData( $tNMLVCustomDraw, "iSubItem" ) = $iSubItem Then Local $hDC = DllStructGetData( $tNMLVCUSTOMDRAW, "hdc" ) ; Device context $aRect = _GUICtrlListView_GetSubItemRect( $hListView, $iItem, $iSubItem ) ; Subitem rectangle $aRect[2] = $aRect[0] + _GUICtrlListView_GetColumnWidth( $hListView, $iSubItem ) DllStructSetData( $tRect, "Left", $aRect[0]+4 ) DllStructSetData( $tRect, "Top", $aRect[1] ) DllStructSetData( $tRect, "Right", $aRect[2] ) DllStructSetData( $tRect, "Bottom", $aRect[3] ) _WinAPI_FillRect( $hDC, $tRect, $hBrush ) ; Fill subitem background _WinAPI_SetTextColor( $hDC, 0x000000 ) ; Set black text color DllStructSetData( $tRect, "Left", DllStructGetData( $tRect, "Left" ) + 2 ) ; Adjust rectangle If $bNotXP Then DllStructSetData( $tRect, "Top", DllStructGetData( $tRect, "Top" ) + 2 ) _WinAPI_DrawText( $hDC, StringSplit($RowsArray[$iItem+2],$TabSep)[$iSubItem+1], $tRect, $DT_WORD_ELLIPSIS ) ; Draw text EndIf Return $CDRF_NEWFONT ; $CDRF_NEWFONT must be returned after changing font or colors EndSwitch Case $NM_CLICK If Not $bComboDoNotOpen And Not $bComboOpenOnDoubleClick And $iItem > -1 And $iSubItem > -1 Then _ GUICtrlSendToDummy( $idComboOpen ) ; Send message to open ComboBox Case $NM_DBLCLK If $bComboOpenOnDoubleClick And $iItem > -1 And $iSubItem > -1 Then _ GUICtrlSendToDummy( $idComboOpen ) ; Send message to open ComboBox EndSwitch EndSwitch Return $GUI_RUNDEFMSG EndFunc ; Handle ListView messages related to ComboBox Func ListViewCallback( $hWnd, $iMsg, $wParam, $lParam, $iSubclassId, $pData ) Switch $iMsg ; Open ComboBox on Enter key Case $WM_GETDLGCODE Switch $wParam Case $VK_RETURN If Not $bComboDoNotOpen And $bComboOpenOnEnter And $iItem > -1 And $iSubItem > -1 Then _GUICtrlListView_SetItemSelected( $hListView, -1, False ) _GUICtrlListView_SetItemSelected( $hListView, $iItem ) GUICtrlSendToDummy( $idComboOpen ) EndIf EndSwitch ; Manage multiple selections ; Prevent ComboBox from opening ; Manage keyboard events Case $WM_KEYDOWN Switch $wParam Case $VK_SHIFT, $VK_CONTROL $bComboDoNotOpen = True ; Manage keyboard events Case $VK_LEFT If Not $bComboDoNotOpen And $iSubItem > 0 Then $iSubItem -= 1 _GUICtrlListView_RedrawItems( $hListView, $iItem, $iItem ) Case $VK_RIGHT If Not $bComboDoNotOpen And $iSubItem < _GUICtrlListView_GetColumnCount( $hListView ) - 1 Then $iSubItem += 1 _GUICtrlListView_RedrawItems( $hListView, $iItem, $iItem ) Case $VK_SPACE If Not $bComboDoNotOpen And $bComboOpenOnSpace And $iItem > -1 And $iSubItem > -1 Then _GUICtrlListView_SetItemSelected( $hListView, -1, False ) GUICtrlSendToDummy( $idComboOpen ) EndIf EndSwitch Case $WM_KEYUP Switch $wParam Case $VK_SHIFT, $VK_CONTROL $bComboDoNotOpen = False EndSwitch ; Left click in ListView ; Sent on single and double click ; Determines item/subitem of the cell that's clicked Case $WM_LBUTTONDOWN Local $aHit = _GUICtrlListView_SubItemHitTest( $hListView ) If $bComboOpen Then ; If another ComboBox is open then delete it _GUICtrlEDIT_Destroy( $hEdit ) GUICtrlSendToDummy( $idComboClose ) _WinAPI_SetFocus( $hListView ) EndIf If $aHit[0] > -1 And $aHit[1] > -1 Then $iItem = $aHit[0] $iSubItem = $aHit[1] _GUICtrlListView_RedrawItems( $hListView, $iItem, $iItem ) EndIf ; Delete ComboBox on right click in ListView and on left ; or right click in non-client ListView area (Scrollbars). Case $WM_RBUTTONDOWN, $WM_NCLBUTTONDOWN, $WM_NCRBUTTONDOWN _GUICtrlEDIT_Destroy( $hEdit ) GUICtrlSendToDummy( $idComboClose ) _WinAPI_SetFocus( $hListView ) EndSwitch ; Call next function in subclass chain Return DllCall( "comctl32.dll", "lresult", "DefSubclassProc", "hwnd", $hWnd, "uint", $iMsg, "wparam", $wParam, "lparam", $lParam )[0] #forceref $iSubclassId, $pData EndFunc ; Messages from the Edit control of the ComboBox Func EditCallback( $hWnd, $iMsg, $wParam, $lParam, $iSubclassId, $pData ) Switch $iMsg ; Dialog codes Case $WM_GETDLGCODE Switch $wParam Case $VK_TAB ; Close GUICtrlSendToDummy( $idComboClose, True ) Case $VK_RETURN ; Accept and close GUICtrlSendToDummy( $idComboClose, True ) Case $VK_ESCAPE ; Close GUICtrlSendToDummy( $idComboClose, True ) _WinAPI_SetFocus( $hListView ) $bEditEscape = True EndSwitch ; Double click in Edit part of ComboBox Case $WM_LBUTTONDBLCLK Local $aPos = MouseGetWindowPos( $hListView ) If $aPos[0] > $aRect[0] And $aPos[0] < $aRect[2] And $aPos[1] > $aRect[1] And $aPos[1] < $aRect[1] + 20 Then _ GUICtrlSendToDummy( $idComboClose, True ) ; Accept and close EndSwitch ; Call next function in subclass chain Return DllCall( "comctl32.dll", "lresult", "DefSubclassProc", "hwnd", $hWnd, "uint", $iMsg, "wparam", $wParam, "lparam", $lParam )[0] #forceref $iSubclassId, $pData EndFunc ; Handle GUI messages related to ComboBox control Func GuiCallback( $hWnd, $iMsg, $wParam, $lParam, $iSubclassId, $pData ) Switch $iMsg ; Delete ComboBox on left or right mouse click in non-client GUI area and on GUI deactivate Case $WM_NCLBUTTONDOWN, $WM_NCRBUTTONDOWN, $WM_ACTIVATE _GUICtrlEDIT_Destroy( $hEdit ) GUICtrlSendToDummy( $idComboClose ) EndSwitch ; Call next function in subclass chain Return DllCall( "comctl32.dll", "lresult", "DefSubclassProc", "hwnd", $hWnd, "uint", $iMsg, "wparam", $wParam, "lparam", $lParam )[0] #forceref $iSubclassId, $pData EndFunc ; Get mouse pos relative to window Func MouseGetWindowPos( $hWindow ) Local $aPos = MouseGetPos() Local $tPoint = DllStructCreate( "int X;int Y" ) DllStructSetData( $tPoint, "X", $aPos[0] ) DllStructSetData( $tPoint, "Y", $aPos[1] ) _WinAPI_ScreenToClient( $hWindow, $tPoint ) $aPos[0] = DllStructGetData( $tPoint, "X" ) $aPos[1] = DllStructGetData( $tPoint, "Y" ) Return $aPos EndFunc  
       
       
       
      OnefolderWorking.zip
    • j0kky
      By j0kky
      Hi guys,
      thanks to this request, I wrote my version of GetLogicalProcessorInformation UDF for x86 e x64:
      ; #FUNCTION# ======================================================================================================================== ; Name...........: _WinAPI_GetLogicalProcessorInformation ; Description ...: Retrieves information about logical processors and related hardware. ; Syntax.........: _WinAPI_GetLogicalProcessorInformation() ; Return values .: On success it returns a bidimensional array: on rows there is the list of processor sets, these are the columns: ; |[0] - A logical processor affinity mask, which indicates the logical processors that the information applies to. ; |[1] - If setted, then the specified logical processors share a single processor core. ; |[2] - How many active processors that share functional units are in the relationship ; (it is setted only if the previous element is setted too) ; |[3] - If setted, it identifies the NUMA node (it can be 0). ; |[4] - If setted, the specified logical processors share a physical package. ; |[5] - A bidimensional array: on rows there is the cache list, these are the columns: ; |[0] - The cache level ; |[1] - The cache associativity ; |[2] - The cache line size, in bytes ; |[3] - The cache size, in bytes ; |[4] - The cache type ; On failure it returns -1 and sets @error to non zero: ; |-1 - internal error ; |-2 - missing DLL (Ws2_32.dll) ; Remarks .......: Search GetLogicalProcessorInformation in MSDN Library. ; Author ........: j0kky ; Modified ......: 1.0.0 ; Links .........: https://msdn.microsoft.com/it-it/library/windows/desktop/ms683194(v=vs.85).aspx ; ==================================================================================================================================== Func _WinAPI_GetLogicalProcessorInformation() Local $hDll = DllOpen("kernel32.dll") If @error Then Return SetError(-2, 0, -1) Local Const $ERROR_INSUFFICIENT_BUFFER = 122 Local $aRet = DllCall($hDll, "BOOL", "GetLogicalProcessorInformation", "ptr", Null, "dword*", 0) If @error Or Not (DllCall($hDll, "DWORD", "GetLastError")[0] = $ERROR_INSUFFICIENT_BUFFER) Then DllClose($hDll) Return SetError(-1, 0, -1) EndIf Local $nReturnLength = $aRet[2] Local $tBuffer = DllStructCreate("byte[" & $nReturnLength & "]") Local $pBuffer = DllStructGetPtr($tBuffer) $aRet = DllCall($hDll, "BOOL", "GetLogicalProcessorInformation", "ptr", $pBuffer, "dword*", $nReturnLength) If @error Or Not $aRet[0] Then DllClose($hDll) Return SetError(-1, 0, -1) EndIf Local Const $tagSYSTEM_LOGICAL_PROCESSOR_INFORMATION = "ULONG_PTR ProcessorMask; INT_PTR Relationship; BYTE UnionBuffer[16]" Local $tSYSTEM_LOGICAL_PROCESSOR_INFORMATION = DllStructCreate($tagSYSTEM_LOGICAL_PROCESSOR_INFORMATION, $pBuffer) Local $nSize = DllStructGetSize($tSYSTEM_LOGICAL_PROCESSOR_INFORMATION), $tCACHE_DESCRIPTOR, _ $aResult[1][6], _ ;mask, core, logical, numa, package, cache $aCacheModel[0][5], _ ;level, associativity, line size, size, processor cache type $nOffset = 0, $nArraySize, $aCache, $vProcessor, $nProcessorMask $aResult[0][0] = $tSYSTEM_LOGICAL_PROCESSOR_INFORMATION.ProcessorMask $aResult[0][5] = $aCacheModel Do $tSYSTEM_LOGICAL_PROCESSOR_INFORMATION = DllStructCreate($tagSYSTEM_LOGICAL_PROCESSOR_INFORMATION, $pBuffer + $nOffset) $nProcessorMask = $tSYSTEM_LOGICAL_PROCESSOR_INFORMATION.ProcessorMask $nArraySize = UBound($aResult) For $i = 0 To ($nArraySize - 1) If $aResult[$i][0] = $nProcessorMask Then $vProcessor = $i ExitLoop EndIf Next If $vProcessor = Null Then ReDim $aResult[$nArraySize + 1][6] $aResult[$nArraySize][0] = $nProcessorMask $aResult[$nArraySize][5] = $aCacheModel $vProcessor = $nArraySize EndIf Switch $tSYSTEM_LOGICAL_PROCESSOR_INFORMATION.Relationship Case 0 ;RelationProcessorCore $aResult[$vProcessor][1] += 1 If (DllStructCreate("byte Flags", DllStructGetPtr($tSYSTEM_LOGICAL_PROCESSOR_INFORMATION, "UnionBuffer")).Flags) = 1 Then For $i = 1 To (($nSize = 24) ? 32 : 64) $aResult[$vProcessor][2] += (Mod($nProcessorMask, 2) ? 1 : 0) $nProcessorMask = Floor($nProcessorMask / 2) Next EndIf Case 1 ;RelationNumaNode $aResult[$vProcessor][3] = DllStructCreate("dword NodeNumber", DllStructGetPtr($tSYSTEM_LOGICAL_PROCESSOR_INFORMATION, "UnionBuffer")).NodeNumber Case 2 ;RelationCache $tCACHE_DESCRIPTOR = DllStructCreate("byte Level; byte Associativity; word LineSize; dword Size; INT Type", _ DllStructGetPtr($tSYSTEM_LOGICAL_PROCESSOR_INFORMATION, "UnionBuffer")) $aCache = $aResult[$vProcessor][5] $nArraySize = UBound($aCache) ReDim $aCache[$nArraySize + 1][5] $aCache[$nArraySize][0] = $tCACHE_DESCRIPTOR.Level $aCache[$nArraySize][1] = $tCACHE_DESCRIPTOR.Associativity $aCache[$nArraySize][2] = $tCACHE_DESCRIPTOR.LineSize $aCache[$nArraySize][3] = $tCACHE_DESCRIPTOR.Size $aCache[$nArraySize][4] = $tCACHE_DESCRIPTOR.Type $aResult[$vProcessor][5] = $aCache Case 3 ;RelationProcessorPackage $aResult[$vProcessor][4] += 1 EndSwitch $nOffset += $nSize $vProcessor = Null Until $nOffset = $nReturnLength DllClose($hDll) Return $aResult EndFunc ;==>_WinAPI_GetLogicalProcessorInformation Usage example:
      #include <array.au3> $array = _WinAPI_GetLogicalProcessorInformation() _ArrayDisplay($array, "Processor set list:") For $i = 0 To UBound($array) - 1 _ArrayDisplay($array[$i][5], "Processor set " & $i + 1 & " cache:") Next