milos83
Active Members-
Posts
89 -
Joined
-
Last visited
Recent Profile Visitors
The recent visitors block is disabled and is not being shown to other users.
milos83's Achievements
-
Confused by AdlibRegister/AdlibUnRegister
milos83 replied to milos83's topic in AutoIt General Help and Support
Both of you are missing the point. I am Unregistering AdLib so it doesn't trigger again right after finishing. My assumption was that by unregistering and then re-registering it at the very exit of the function, it will have a 1s delay between function runs. This is not the case. It runs right away. Why is this? From the helpfile : This is not true if done from the actual function. -
Using latest Autoit The following code never gets to the third line (msgbox). Why? CheckWorkers() Sleep(1000) MsgBox(0,0,0);never gets here Func CheckWorkers() AdlibUnRegister("CheckWorkers") Sleep(1000) AdlibRegister("CheckWorkers", 1000) EndFunc The bottom line is, if the duration of the function is >= Adlib interval, it will run forever. No matter if you did AdlibUnRegister on function start or not.
-
milos83 reacted to a post in a topic:
Websocket unmask/decode received data (Websocket framing) - SOLVED
-
milos83 reacted to a post in a topic:
Websocket unmask/decode received data (Websocket framing) - SOLVED
-
Thank buddy for looking at it! I managed to solve it finally! The issue was what I already suspected and played with before, the Sec-WebSocket-Extensions Just leaving it out will make the client post messages without compression! Here is the fixed code that works! #include <Array.au3> #include <Crypt.au3> TCPStartup() Global $gSocket = TCPListen("127.0.0.1", 65432) While True Local $client = TCPAccept($gSocket) If $client <> -1 Then Local $data = TCPRecv($client, 1024) If StringInStr($data, "Sec-WebSocket-Key:") Then ; Perform WebSocket handshake Local $key = StringRegExp($data, "Sec-WebSocket-Key: (.+)", 1)[0] ConsoleWrite($data & @CRLF) ConsoleWrite("$key:" & $key & @CRLF) Local $responseKey = base64(_Crypt_HashData($key & "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", $CALG_SHA1)) Local $response = "HTTP/1.1 101 Switching Protocols" & @CRLF & _ "Upgrade: websocket" & @CRLF & _ "Connection: Upgrade" & @CRLF & _ "Sec-WebSocket-Accept: " & $responseKey & @CRLF & @CRLF TCPSend($client, $response) Sleep(1000) WebSocketSend($client, "Hello!"); This works Sleep(1000) ; Now the connection is upgraded to WebSocket, handle communication While True Local $message = WebSocketReceive($client) If @error Then ContinueLoop If $message <> "" Then ; Handle the received message ConsoleWrite("Received message: " & $message & @CRLF) EndIf WEnd EndIf EndIf WEnd Func WebSocketReceive($socket) Local $bytes = TCPRecv($socket, 4096) ; Adjust buffer size as needed If @error Or StringLen($bytes) = 0 Then Return SetError(1, 0, 0) ; Error reading data Return unmask(BinaryToString($bytes)) EndFunc Func WebSocketSend($socket, $message) Local $length = StringLen($message) Local $header = Chr(BitOR(0x80, 0x01)) ; FIN, Opcode Text If $length <= 125 Then $header &= Chr($length) ElseIf $length <= 65535 Then $header &= Chr(126) & Chr(BitShift($length, 8)) & Chr(BitAND($length, 0xFF)) Else $header &= Chr(127) For $i = 7 To 0 Step -1 $header &= Chr(BitShift($length, 8 * $i)) Next EndIf TCPSend($socket, $header & $message) EndFunc ;============================================================================================================================== ; Function: base64($vCode [, $bEncode = True [, $bUrl = False]]) ; ; Description: Decode or Encode $vData using Microsoft.XMLDOM to Base64Binary or Base64Url. ; IMPORTANT! Encoded base64url is without @LF after 72 lines. Some websites may require this. ; ; Parameter(s): $vData - string or integer | Data to encode or decode. ; $bEncode - boolean | True - encode, False - decode. ; $bUrl - boolean | True - output is will decoded or encoded using base64url shema. ; ; Return Value(s): On Success - Returns output data ; On Failure - Returns 1 - Failed to create object. ; ; Author (s): (Ghads on Wordpress.com), Ascer ;=============================================================================================================================== Func base64($vCode, $bEncode = True, $bUrl = False) Local $oDM = ObjCreate("Microsoft.XMLDOM") If Not IsObj($oDM) Then Return SetError(1, 0, 1) Local $oEL = $oDM.createElement("Tmp") $oEL.DataType = "bin.base64" If $bEncode then $oEL.NodeTypedValue = Binary($vCode) If Not $bUrl Then Return $oEL.Text Return StringReplace(StringReplace(StringReplace($oEL.Text, "+", "-"),"/", "_"), @LF, "") Else If $bUrl Then $vCode = StringReplace(StringReplace($vCode, "-", "+"), "_", "/") $oEL.Text = $vCode Return $oEL.NodeTypedValue EndIf EndFunc ;==>base64 Func unmask($text) Local $length = StringToBinary(StringMid($text, 2, 1)) $length = BitAND(Number($length), 127) Local $masks, $data If $length = 126 Then $masks = StringMid($text, 5, 4) $data = StringMid($text, 9) ElseIf $length = 127 Then $masks = StringMid($text, 11, 4) $data = StringMid($text, 15) Else $masks = StringMid($text, 3, 4) $data = StringMid($text, 7) EndIf Local $result = "" For $i = 0 To StringLen($data) - 1 $result &= Chr(BitXOR(Asc(StringMid($data, $i + 1, 1)), Asc(StringMid($masks, Mod($i, 4) + 1, 1)))) Next Return $result EndFunc
-
I created a WebSocket server and Google Chrome addon is connecting to it. Handshake works and the server can send messages to the addon just fine. The problem are messages that the addon is sending to the server. The data is received but, I just can't decrypt the received data and I tried a lot of different solutions. The add-on part is working as it should because in one of my tests, I ran a simplest c# WebSocket server(see end of the post) on the same port and it gets the data properly. Whatever I tried, I always get gibberish output. eg: ÊÍÌÉ/ Does anyone knows how to unframe/unmask the WebSocket data properly? These are some of my tries: $bytes = TCPRecv($socket, 4096) ConsoleWrite(unmask($bytes)) Func unmask($text) Local $length = StringToBinary(StringMid($text, 2, 1)) $length = BitAND(Number($length), 127) ConsoleWrite($length & @CRLF) Local $masks, $data If $length = 126 Then $masks = StringMid($text, 5, 4) $data = StringMid($text, 9) ElseIf $length = 127 Then $masks = StringMid($text, 11, 4) $data = StringMid($text, 15) Else $masks = StringMid($text, 3, 4) $data = StringMid($text, 7) EndIf Local $result = "" For $i = 0 To StringLen($data) - 1 $result &= Chr(BitXOR(Asc(StringMid($data, $i + 1, 1)), Asc(StringMid($masks, Mod($i, 4) + 1, 1)))) Next Return $result EndFunc Another try: Func WebSocketReceive($socket) Local $bytes = TCPRecv($socket, 4096) ; Adjust buffer size as needed If @error Or StringLen($bytes) = 0 Then Return SetError(1, 0, 0) ; Error reading data ConsoleWrite(unmask(BinaryToString($bytes)) & @CRLF); another try (function unmask = line ~190) ; Convert binary to byte array Local $byteArray = $bytes Local $fin = BitAND(BinaryMid($byteArray, 1, 1), 0x80) <> 0 $mask = BitAND(BinaryMid($byteArray, 2, 1), 0x80) <> 0 ; must be true, "All messages from the client to the server have this bit set" Local $opcode = BitAND(BinaryMid($byteArray, 1, 1), 0x0F) ; expecting 1 - text message $offset = 2 Local $msglen = BitAND(BinaryMid($byteArray, 2, 1), 0x7F) If $msglen == 126 Then ; bytes are reversed because the WebSocket will print them in Big-Endian ; whereas BitConverter will want them arranged in little-endian on Windows $msglen = BitShift(BitOR(BinaryMid($byteArray, 4, 1), BitShift(BinaryMid($byteArray, 3, 1), 8)), 0) $offset = 4 ElseIf $msglen == 127 Then ; To test the below code, we need to manually buffer larger messages $msglen = BitOR(BitShift(BinaryMid($byteArray, 10, 1), 56), BitShift(BinaryMid($byteArray, 9, 1), 48), _ BitShift(BinaryMid($byteArray, 8, 1), 40), BitShift(BinaryMid($byteArray, 7, 1), 32), _ BitShift(BinaryMid($byteArray, 6, 1), 24), BitShift(BinaryMid($byteArray, 5, 1), 16), _ BitShift(BinaryMid($byteArray, 4, 1), 8), BinaryMid($byteArray, 3, 1)) $offset = 10 EndIf If $msglen == 0 Then ConsoleWrite("msglen == 0" & @CRLF) ElseIf $mask Then Local $decoded[$msglen] Local $masks[4] = [BinaryMid($byteArray, $offset, 1), BinaryMid($byteArray, $offset + 1, 1), _ BinaryMid($byteArray, $offset + 2, 1), BinaryMid($byteArray, $offset + 3, 1)] $offset += 4 For $i = 0 To $msglen - 1 $decoded[$i] = BitXOR(BinaryMid($byteArray, $offset + $i, 1), $masks[Mod($i, 4)]) Next Local $text = BinaryToString(Binary($decoded)) ConsoleWrite($text & @CRLF) Return $text Else ConsoleWrite("mask bit not set" & @CRLF) EndIf Return SetError(1, 0, "") EndFunc And the whole code: #include <Array.au3> #include <Crypt.au3> #include <WinHttp.au3> #include <APIErrorsConstants.au3> #include <AutoItConstants.au3> TCPStartup() Global $gSocket = TCPListen("127.0.0.1", 65432) While True Local $client = TCPAccept($gSocket) If $client <> -1 Then Local $data = TCPRecv($client, 1024) If StringInStr($data, "Sec-WebSocket-Key:") Then ; Perform WebSocket handshake Local $key = StringRegExp($data, "Sec-WebSocket-Key: (.+)", 1)[0] ConsoleWrite($data & @CRLF) ConsoleWrite("$key:" & $key & @CRLF) Local $responseKey = base64(_Crypt_HashData($key & "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", $CALG_SHA1)) Local $response = "HTTP/1.1 101 Switching Protocols" & @CRLF & _ "Upgrade: websocket" & @CRLF & _ "Connection: Upgrade" & @CRLF & _ "Sec-WebSocket-Extensions: permessage-deflate; server_no_context_takeover; client_no_context_takeover" & @CRLF & _ "Sec-WebSocket-Accept: " & $responseKey & @CRLF & @CRLF ; ;"Sec-WebSocket-Extensions: no-masking" & @CRLF & _ TCPSend($client, $response) Sleep(1000) WebSocketSend($client, "Hello!"); This works Sleep(1000) ; Now the connection is upgraded to WebSocket, handle communication While True Local $message = WebSocketReceive($client) If @error Then ContinueLoop ; Connection closed If $message <> "" Then ; Handle the received message ConsoleWrite("Received message: " & $message & @CRLF) ConsoleWrite("Received message: " & BinaryToString($message) & @CRLF) EndIf WEnd EndIf EndIf WEnd Func WebSocketReceive($socket) Local $bytes = TCPRecv($socket, 4096) ; Adjust buffer size as needed If @error Or StringLen($bytes) = 0 Then Return SetError(1, 0, 0) ; Error reading data ConsoleWrite(unmask(BinaryToString($bytes)) & @CRLF); another try (function unmask = line ~190) ; Convert binary to byte array Local $byteArray = $bytes Local $fin = BitAND(BinaryMid($byteArray, 1, 1), 0x80) <> 0 $mask = BitAND(BinaryMid($byteArray, 2, 1), 0x80) <> 0 ; must be true, "All messages from the client to the server have this bit set" Local $opcode = BitAND(BinaryMid($byteArray, 1, 1), 0x0F) ; expecting 1 - text message $offset = 2 Local $msglen = BitAND(BinaryMid($byteArray, 2, 1), 0x7F) If $msglen == 126 Then ; bytes are reversed because the WebSocket will print them in Big-Endian ; whereas BitConverter will want them arranged in little-endian on Windows $msglen = BitShift(BitOR(BinaryMid($byteArray, 4, 1), BitShift(BinaryMid($byteArray, 3, 1), 8)), 0) $offset = 4 ElseIf $msglen == 127 Then ; To test the below code, we need to manually buffer larger messages $msglen = BitOR(BitShift(BinaryMid($byteArray, 10, 1), 56), BitShift(BinaryMid($byteArray, 9, 1), 48), _ BitShift(BinaryMid($byteArray, 8, 1), 40), BitShift(BinaryMid($byteArray, 7, 1), 32), _ BitShift(BinaryMid($byteArray, 6, 1), 24), BitShift(BinaryMid($byteArray, 5, 1), 16), _ BitShift(BinaryMid($byteArray, 4, 1), 8), BinaryMid($byteArray, 3, 1)) $offset = 10 EndIf If $msglen == 0 Then ConsoleWrite("msglen == 0" & @CRLF) ElseIf $mask Then Local $decoded[$msglen] Local $masks[4] = [BinaryMid($byteArray, $offset, 1), BinaryMid($byteArray, $offset + 1, 1), _ BinaryMid($byteArray, $offset + 2, 1), BinaryMid($byteArray, $offset + 3, 1)] $offset += 4 For $i = 0 To $msglen - 1 $decoded[$i] = BitXOR(BinaryMid($byteArray, $offset + $i, 1), $masks[Mod($i, 4)]) Next Local $text = BinaryToString(Binary($decoded)) ConsoleWrite($text & @CRLF) Return $text Else ConsoleWrite("mask bit not set" & @CRLF) EndIf Return SetError(1, 0, "") EndFunc Func WebSocketSend($socket, $message) Local $length = StringLen($message) Local $header = Chr(BitOR(0x80, 0x01)) ; FIN, Opcode Text If $length <= 125 Then $header &= Chr($length) ElseIf $length <= 65535 Then $header &= Chr(126) & Chr(BitShift($length, 8)) & Chr(BitAND($length, 0xFF)) Else $header &= Chr(127) For $i = 7 To 0 Step -1 $header &= Chr(BitShift($length, 8 * $i)) Next EndIf ;~ ConsoleWrite("send:" & $header & $message & @CRLF) TCPSend($socket, $header & $message) EndFunc ;============================================================================================================================== ; Function: base64($vCode [, $bEncode = True [, $bUrl = False]]) ; ; Description: Decode or Encode $vData using Microsoft.XMLDOM to Base64Binary or Base64Url. ; IMPORTANT! Encoded base64url is without @LF after 72 lines. Some websites may require this. ; ; Parameter(s): $vData - string or integer | Data to encode or decode. ; $bEncode - boolean | True - encode, False - decode. ; $bUrl - boolean | True - output is will decoded or encoded using base64url shema. ; ; Return Value(s): On Success - Returns output data ; On Failure - Returns 1 - Failed to create object. ; ; Author (s): (Ghads on Wordpress.com), Ascer ;=============================================================================================================================== Func base64($vCode, $bEncode = True, $bUrl = False) Local $oDM = ObjCreate("Microsoft.XMLDOM") If Not IsObj($oDM) Then Return SetError(1, 0, 1) Local $oEL = $oDM.createElement("Tmp") $oEL.DataType = "bin.base64" If $bEncode then $oEL.NodeTypedValue = Binary($vCode) If Not $bUrl Then Return $oEL.Text Return StringReplace(StringReplace(StringReplace($oEL.Text, "+", "-"),"/", "_"), @LF, "") Else If $bUrl Then $vCode = StringReplace(StringReplace($vCode, "-", "+"), "_", "/") $oEL.Text = $vCode Return $oEL.NodeTypedValue EndIf EndFunc ;==>base64 Func unmask($text) Local $length = StringToBinary(StringMid($text, 2, 1)) $length = BitAND(Number($length), 127) ConsoleWrite($length & @CRLF) Local $masks, $data If $length = 126 Then $masks = StringMid($text, 5, 4) $data = StringMid($text, 9) ElseIf $length = 127 Then $masks = StringMid($text, 11, 4) $data = StringMid($text, 15) Else $masks = StringMid($text, 3, 4) $data = StringMid($text, 7) EndIf Local $result = "" For $i = 0 To StringLen($data) - 1 $result &= Chr(BitXOR(Asc(StringMid($data, $i + 1, 1)), Asc(StringMid($masks, Mod($i, 4) + 1, 1)))) Next Return $result EndFunc There is no place I haven't searched. Perfectly working c# server using System; using System.Net; using System.Net.Sockets; using System.Text; using System.Text.RegularExpressions; class Server { public static void Main() { string ip = "127.0.0.1"; int port = 65432; var server = new TcpListener(IPAddress.Parse(ip), port); server.Start(); Console.WriteLine("Server has started on {0}:{1}, Waiting for a connection…", ip, port); TcpClient client = server.AcceptTcpClient(); Console.WriteLine("A client connected."); NetworkStream stream = client.GetStream(); // enter to an infinite cycle to be able to handle every change in stream while (true) { while (!stream.DataAvailable) ; while (client.Available < 3) ; // match against "get" byte[] bytes = new byte[client.Available]; stream.Read(bytes, 0, bytes.Length); string s = Encoding.UTF8.GetString(bytes); if (Regex.IsMatch(s, "^GET", RegexOptions.IgnoreCase)) { Console.WriteLine("=====Handshaking from client=====\n{0}", s); // 1. Obtain the value of the "Sec-WebSocket-Key" request header without any leading or trailing whitespace // 2. Concatenate it with "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" (a special GUID specified by RFC 6455) // 3. Compute SHA-1 and Base64 hash of the new value // 4. Write the hash back as the value of "Sec-WebSocket-Accept" response header in an HTTP response string swk = Regex.Match(s, "Sec-WebSocket-Key: (.*)").Groups[1].Value.Trim(); string swka = swk + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; byte[] swkaSha1 = System.Security.Cryptography.SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(swka)); string swkaSha1Base64 = Convert.ToBase64String(swkaSha1); // HTTP/1.1 defines the sequence CR LF as the end-of-line marker byte[] response = Encoding.UTF8.GetBytes( "HTTP/1.1 101 Switching Protocols\r\n" + "Connection: Upgrade\r\n" + "Upgrade: websocket\r\n" + "Sec-WebSocket-Accept: " + swkaSha1Base64 + "\r\n\r\n"); stream.Write(response, 0, response.Length); } else { bool fin = (bytes[0] & 0b10000000) != 0, mask = (bytes[1] & 0b10000000) != 0; // must be true, "All messages from the client to the server have this bit set" Console.WriteLine(mask); int opcode = bytes[0] & 0b00001111, // expecting 1 - text message offset = 2; ulong msglen = bytes[1] & (ulong)0b01111111; Console.WriteLine(msglen); if (msglen == 126) { // bytes are reversed because websocket will print them in Big-Endian, whereas // BitConverter will want them arranged in little-endian on windows msglen = BitConverter.ToUInt16(new byte[] { bytes[3], bytes[2] }, 0); offset = 4; } else if (msglen == 127) { // To test the below code, we need to manually buffer larger messages — since the NIC's autobuffering // may be too latency-friendly for this code to run (that is, we may have only some of the bytes in this // websocket frame available through client.Available). msglen = BitConverter.ToUInt64(new byte[] { bytes[9], bytes[8], bytes[7], bytes[6], bytes[5], bytes[4], bytes[3], bytes[2] }, 0); offset = 10; } if (msglen == 0) { Console.WriteLine("msglen == 0"); } else if (mask) { byte[] decoded = new byte[msglen]; byte[] masks = new byte[4] { bytes[offset], bytes[offset + 1], bytes[offset + 2], bytes[offset + 3] }; offset += 4; for (ulong i = 0; i < msglen; ++i) decoded[i] = (byte)(bytes[(ulong)offset + i] ^ masks[i % 4]); string text = Encoding.UTF8.GetString(decoded); Console.WriteLine("{0}", text); } else Console.WriteLine("mask bit not set"); Console.WriteLine(); } } } } If someone has a suggestion, please help Thanks in advance!
-
milos83 reacted to a post in a topic:
Old style drag window
-
Nice!
-
milos83 reacted to a post in a topic:
True AutoIt multi-threading!
-
milos83 reacted to a post in a topic:
5 lines script and GUIDelete() crashes?!
-
5 lines script and GUIDelete() crashes?!
milos83 replied to milos83's topic in AutoIt General Help and Support
Yeah, that is what I was doing. I would stringify all of the data, 'null' the json and the load the data back in but its not as effective at memory clearing as expected. Ended up just decreasing the usage of json since it has that memory leak. Thanks @Danyfirex -
milos83 reacted to a post in a topic:
5 lines script and GUIDelete() crashes?!
-
5 lines script and GUIDelete() crashes?!
milos83 replied to milos83's topic in AutoIt General Help and Support
Thank you Danyfirex, Here is why I wanted to do it, The ScriptControl is hogging up RAM on a long term usage so I was thinking if I attach it to a GUI and then deleting that GUI would free the memory. I was also thinking creating a ScriptControl object from another proccess and then attaching to it then I would be able to kill the proccess periodically and clear the memory. But that never worked since ObjGet can't attach to another proccess obj. Anyone have a suggestion? To further clarify, I am using OO_JSON.au3 and it uses a ScriptControl in order to parse JSON. Its faster than any solution out there but simply setting a json value in a loop would build up RAM fast.\So im searching for a solution to clear it. Thanks in advance -
I am creating a gui and a ScriptControl in it. When I run GUIDelete it crashes. What am I doing wrong? GUICreate("") $sc = ObjCreate("ScriptControl");MSScriptControl.ScriptControl acts the same GUICtrlCreateObj($sc, 0, 0) GUISetState() GUIDelete();hang message: Autoit stopped working! Not every control can be embedded. They must at least support an 'IDispatch' interface. Is that the issue here? As the Danyfirex said, ScriptControl can't be attached to a GUI. Here is why I wanted to do it, The ScriptControl is hogging up RAM on a long term usage so I was thinking if I attach it to a GUI and then deleting that GUI would free the memory. I was also thinking creating a ScriptControl object from another process and then attaching to it so then I would be able to kill the process periodically and clear the memory. But that never worked since ObjGet can't attach to another proccess obj. To further clarify, I am using OO_JSON.au3 and it uses a ScriptControl in order to parse JSON. Its faster than any solution out there but, simply setting a json value in a loop would build up RAM fast. So I'm searching for a solution to clear it. Anyone have a suggestion?
-
Did anyone got the working code out of this? As in screen capturing. @JRSmile You said you managed to get it to save to bmp. Can you share that code?
-
Oh, then I misused it. I thought its for using the default values (same as when you don't supply one). Actually I have been using Default for quite some time and either I got lucky or its partially implemented in that way. Regards
-
Default keyword for optional parameter is interpreted wrongly. ConsoleWrite(StringReplace("aa", "a", "b", Default, 1) & @CRLF) StringReplace ( "string", "searchstring/start", "replacestring" [, occurrence = 0 [, casesense = 0]] ) The code above will output ab even thou the default value for the occurrence is 0 (replace all). Of course using zero instead of Default will work fine.
-
That does the trick! Since I don't know if there are any side effects I am using this alternative only if WIN7+AeroOFF. Func _ScreenCapture_Capture2($sFileName = "", $iLeft = 0, $iTop = 0, $iRight = -1, $iBottom = -1, $bCursor = True) Local $bRet = False If $iRight = -1 Then $iRight = _WinAPI_GetSystemMetrics($__SCREENCAPTURECONSTANT_SM_CXSCREEN) - 1 If $iBottom = -1 Then $iBottom = _WinAPI_GetSystemMetrics($__SCREENCAPTURECONSTANT_SM_CYSCREEN) - 1 If $iRight < $iLeft Then Return SetError(-1, 0, $bRet) If $iBottom < $iTop Then Return SetError(-2, 0, $bRet) Local $iW = ($iRight - $iLeft) + 1 Local $iH = ($iBottom - $iTop) + 1 Local $hWnd = _WinAPI_GetDesktopWindow() Local $hDDC = _WinAPI_GetDC($hWnd) Local $hCDC = _WinAPI_CreateCompatibleDC($hDDC) Local $hBMP = _WinAPI_CreateCompatibleBitmap($hDDC, $iW, $iH) _WinAPI_SelectObject($hCDC, $hBMP) ;~ _WinAPI_BitBlt($hCDC, 0, 0, $iW, $iH, $hDDC, $iLeft, $iTop, $__SCREENCAPTURECONSTANT_SRCCOPY) _WinAPI_BitBlt($hCDC, 0, 0, $iW, $iH, $hDDC, $iLeft, $iTop, BitOR($__SCREENCAPTURECONSTANT_SRCCOPY, $CAPTUREBLT)) If $bCursor Then Local $aCursor = _WinAPI_GetCursorInfo() If Not @error And $aCursor[1] Then $bCursor = True ; Cursor info was found. Local $hIcon = _WinAPI_CopyIcon($aCursor[2]) Local $aIcon = _WinAPI_GetIconInfo($hIcon) If Not @error Then _WinAPI_DeleteObject($aIcon[4]) ; delete bitmap mask return by _WinAPI_GetIconInfo() If $aIcon[5] <> 0 Then _WinAPI_DeleteObject($aIcon[5]); delete bitmap hbmColor return by _WinAPI_GetIconInfo() _WinAPI_DrawIcon($hCDC, $aCursor[3] - $aIcon[2] - $iLeft, $aCursor[4] - $aIcon[3] - $iTop, $hIcon) EndIf _WinAPI_DestroyIcon($hIcon) EndIf EndIf _WinAPI_ReleaseDC($hWnd, $hDDC) _WinAPI_DeleteDC($hCDC) If $sFileName = "" Then Return $hBMP $bRet = _ScreenCapture_SaveImage($sFileName, $hBMP, True) Return SetError(@error, @extended, $bRet) EndFunc ;==>_ScreenCapture_Capture Thank you @InnI