1
+ #include " WinHTTP.au3"
2
+
3
+ #include < WinAPI.au3> ; _WinAPI_GetLastError
4
+ #include < String .au3> ; _HexToString
5
+ #include < EditConstants.au3>
6
+ #include < GUIConstantsEx.au3>
7
+ #include < WindowsConstants.au3>
8
+
9
+ Main()
10
+
11
+ Func Main()
12
+
13
+ Local $bDev = False
14
+ Local $sData = " "
15
+ Local $hSocket = 0
16
+ Local $iTimeout = 500
17
+ Local $bRunning = False
18
+ Local $bSuspended = False
19
+
20
+ Local $bInLevel = False
21
+ Local $bLevelPaused = False
22
+
23
+ If $bDev Then
24
+ Local $hGUI = GUICreate (" Dash Pause" , 640 , 480 , - 1 , - 1 , BitOr ($WS_MINIMIZEBOX , $WS_CAPTION , $WS_SYSMENU ))
25
+ Local $hData = GUICtrlCreateEdit (" " , 0 , 20 , 640 , 460 , BitOR ($ES_MULTILINE , $WS_VSCROLL , $ES_AUTOVSCROLL , $ES_READONLY ))
26
+ GUISetState (@SW_SHOW , $hGUI )
27
+ EndIf
28
+
29
+ While 1
30
+
31
+ $hMsg = GUIGetMsg ()
32
+
33
+ Select
34
+
35
+ Case $hMsg = $GUI_EVENT_CLOSE
36
+ GUIDelete ($hGUI )
37
+ TCPShutdown ()
38
+ Exit
39
+
40
+ Case ProcessExists (" Beat Saber.exe" ) and $hSocket = 0
41
+ TraySetToolTip (" Connecting..." )
42
+ $hSocket = _StartListener(" 127.0.0.1" , 2946 , " /BSDataPuller" )
43
+ TraySetToolTip (" Connected" )
44
+ $bRunning = True
45
+
46
+ Case $hSocket <> 0 And Not ProcessExists (" Beat Saber.exe" )
47
+ TraySetToolTip (" Disconnecting..." )
48
+ _StopListener($hSocket )
49
+ TraySetToolTip (" Disconnected" )
50
+ $bRunning = False
51
+ $hSocket = 0
52
+
53
+ Case $bRunning
54
+ $sData = _GetData($hSocket , $iTimeout )
55
+ If $bDev Then GUICtrlSetData ($hData , $sData )
56
+ $bInLevel = _StringBetween($sData , ' "InLevel": ' , " ," )[0 ]
57
+ $bLevelPaused = _StringBetween($sData , ' "LevelPaused": ' , " ," )[0 ]
58
+ If $bInLevel = " true" And $bLevelPaused = " false" Then
59
+ If Not $bSuspended Then
60
+ ConsoleWrite (" Suspending" & @CRLF )
61
+ _ProcessSuspend(" OculusDash.exe" )
62
+ _ProcessSuspend(" VRDashboard.exe" )
63
+ $bSuspended = True
64
+ EndIf
65
+ ElseIf $bInLevel = " false" Then
66
+ If $bSuspended Then
67
+ ConsoleWrite (" Resuming" & @CRLF )
68
+ _ProcessResume(" OculusDash.exe" )
69
+ _ProcessResume(" VRDashboard.exe" )
70
+ $bSuspended = False
71
+ EndIf
72
+ EndIf
73
+
74
+ Case Else
75
+ ; ;;
76
+
77
+ EndSelect
78
+
79
+ WEnd
80
+
81
+ EndFunc
82
+
83
+ Func _GetData($hWebSocket , $iTimeout )
84
+
85
+ Local $hTimer = TimerInit ()
86
+
87
+ Local Const $WINHTTP_WEB_SOCKET_BINARY_MESSAGE_BUFFER_TYPE = 0
88
+ Local Const $WINHTTP_WEB_SOCKET_BINARY_FRAGMENT_BUFFER_TYPE = 1
89
+ Local Const $WINHTTP_WEB_SOCKET_UTF8_MESSAGE_BUFFER_TYPE = 2
90
+ Local Const $WINHTTP_WEB_SOCKET_UTF8_FRAGMENT_BUFFER_TYPE = 3
91
+
92
+ Local Const $ERROR_NOT_ENOUGH_MEMORY = 8
93
+ Local Const $ERROR_INVALID_PARAMETER = 87
94
+
95
+ Local $iBufferLen = 1024
96
+ Local $tBuffer = 0 , $bRecv = Binary (" " )
97
+
98
+ Local $iBytesRead = 0 , $iBufferType = 3
99
+ Do
100
+ If $iBufferLen = 0 Then
101
+ $iError = $ERROR_NOT_ENOUGH_MEMORY
102
+ Return False
103
+ EndIf
104
+
105
+ $tBuffer = DllStructCreate (" byte[" & $iBufferLen & " ]" )
106
+
107
+ $iError = _WinHttpWebSocketReceive($hWebSocket , _
108
+ $tBuffer , _
109
+ $iBytesRead , _
110
+ $iBufferType )
111
+ If @error Or $iError <> 0 Then
112
+ ConsoleWrite (" WebSocketReceive error" & @CRLF )
113
+ Return False
114
+ EndIf
115
+
116
+ ; If we receive just part of the message restart the receive operation.
117
+
118
+ $bRecv &= BinaryMid (DllStructGetData ($tBuffer , 1 ), 1 , $iBytesRead )
119
+ $tBuffer = 0
120
+
121
+ $iBufferLen -= $iBytesRead
122
+ ; If TimerDiff($hTimer) > $iTimeout Then Return False
123
+ Until $iBufferType <> $WINHTTP_WEB_SOCKET_UTF8_FRAGMENT_BUFFER_TYPE
124
+
125
+ ; We expected server just to echo single binary message.
126
+
127
+ If $iBufferType <> $WINHTTP_WEB_SOCKET_UTF8_MESSAGE_BUFFER_TYPE Then
128
+ ConsoleWrite (" Unexpected buffer type" & @CRLF )
129
+ $iError = $ERROR_INVALID_PARAMETER
130
+ Return False
131
+ EndIf
132
+
133
+ Return _HexToString($bRecv )
134
+
135
+ EndFunc
136
+
137
+ Func _ProcessSuspend($sProcess )
138
+ $iPID = ProcessExists ($sProcess )
139
+ If $iPID Then
140
+ $ai_Handle = DllCall (" kernel32.dll" , ' int' , ' OpenProcess' , ' int' , 0x1f0fff , ' int' , False , ' int' , $iPID )
141
+ $i_success = DllCall (" ntdll.dll" ," int" ," NtSuspendProcess" ," int" ,$ai_Handle [0 ])
142
+ DllCall (' kernel32.dll' , ' ptr' , ' CloseHandle' , ' ptr' , $ai_Handle )
143
+ If IsArray ($i_success ) Then
144
+ Return 1
145
+ Else
146
+ SetError (1 )
147
+ Return 0
148
+ Endif
149
+ Else
150
+ SetError (2 )
151
+ Return 0
152
+ EndIf
153
+ EndFunc
154
+
155
+ Func _ProcessResume($sProcess )
156
+ $iPID = ProcessExists ($sProcess )
157
+ If $iPID Then
158
+ $ai_Handle = DllCall (" kernel32.dll" , ' int' , ' OpenProcess' , ' int' , 0x1f0fff , ' int' , False , ' int' , $iPID )
159
+ $i_success = DllCall (" ntdll.dll" ," int" ," NtResumeProcess" ," int" ,$ai_Handle [0 ])
160
+ DllCall (' kernel32.dll' , ' ptr' , ' CloseHandle' , ' ptr' , $ai_Handle )
161
+ If IsArray ($i_success ) Then
162
+ Return 1
163
+ Else
164
+ SetError (1 )
165
+ Return 0
166
+ Endif
167
+ Else
168
+ SetError (2 )
169
+ Return 0
170
+ EndIf
171
+ EndFunc
172
+
173
+ Func _SendData($hWebSocket , $sData ) ; Why are you using this <_<
174
+
175
+ Local Const $WINHTTP_WEB_SOCKET_BINARY_MESSAGE_BUFFER_TYPE = 0
176
+
177
+ $iError = _WinHttpWebSocketSend($hWebSocket , _
178
+ $WINHTTP_WEB_SOCKET_BINARY_MESSAGE_BUFFER_TYPE , _
179
+ $sData )
180
+ If @error Or $iError <> 0 Then
181
+ ConsoleWrite (" WebSocketSend error" & @CRLF )
182
+ Return False
183
+ EndIf
184
+ Return True
185
+ EndFunc
186
+
187
+ Func _StartListener($sIP = " 127.0.0.1" , $iPort = 1337 , $sPath = " " )
188
+
189
+ Local Const $WINHTTP_OPTION_UPGRADE_TO_WEB_SOCKET = 114
190
+
191
+ $hOpen = _WinHttpOpen(" DashPause 0.1" , $WINHTTP_ACCESS_TYPE_DEFAULT_PROXY )
192
+ If $hOpen = 0 Then
193
+ $iError = _WinAPI_GetLastError()
194
+ ConsoleWrite (" Open error" & @CRLF )
195
+ Return False
196
+ EndIf
197
+
198
+ $hConnect = _WinHttpConnect($hOpen , $sIP , $iPort )
199
+ If $hConnect = 0 Then
200
+ $iError = _WinAPI_GetLastError()
201
+ ConsoleWrite (" Connect error" & @CRLF )
202
+ Return False
203
+ EndIf
204
+
205
+ $hRequest = _WinHttpOpenRequest($hConnect , " GET" , $sPath , " " )
206
+ If $hRequest = 0 Then
207
+ $iError = _WinAPI_GetLastError()
208
+ ConsoleWrite (" OpenRequest error" & @CRLF )
209
+ Return False
210
+ EndIf
211
+
212
+ ; Request protocol upgrade from http to websocket.
213
+
214
+ Local $fStatus = _WinHttpSetOptionNoParams($hRequest , $WINHTTP_OPTION_UPGRADE_TO_WEB_SOCKET )
215
+ If Not $fStatus Then
216
+ $iError = _WinAPI_GetLastError()
217
+ ConsoleWrite (" SetOption error" & @CRLF )
218
+ Return False
219
+ EndIf
220
+
221
+ ; Perform websocket handshake by sending a request and receiving server's response.
222
+ ; Application may specify additional headers if needed.
223
+
224
+ $fStatus = _WinHttpSendRequest($hRequest )
225
+ If Not $fStatus Then
226
+ $iError = _WinAPI_GetLastError()
227
+ ConsoleWrite (" SendRequest error" & @CRLF )
228
+ Return False
229
+ EndIf
230
+
231
+ $fStatus = _WinHttpReceiveResponse($hRequest )
232
+ If Not $fStatus Then
233
+ $iError = _WinAPI_GetLastError()
234
+ ConsoleWrite (" SendRequest error" & @CRLF )
235
+ Return False
236
+ EndIf
237
+
238
+ ; Application should check what is the HTTP status code returned by the server and behave accordingly.
239
+ ; WinHttpWebSocketCompleteUpgrade will fail if the HTTP status code is different than 101.
240
+
241
+ $hWebSocket = _WinHttpWebSocketCompleteUpgrade($hRequest , 0 )
242
+ If $hWebSocket = 0 Then
243
+ $iError = _WinAPI_GetLastError()
244
+ ConsoleWrite (" WebSocketCompleteUpgrade error" & @CRLF )
245
+ Return False
246
+ EndIf
247
+
248
+ _WinHttpCloseHandle($hRequest )
249
+ $hRequestHandle = 0
250
+
251
+ ConsoleWrite (" Succesfully upgraded to websocket protocol" & @CRLF )
252
+ Return $hWebSocket
253
+ EndFunc
254
+
255
+ Func _StopListener($hWebSocket )
256
+
257
+ Local Const $WINHTTP_WEB_SOCKET_SUCCESS_CLOSE_STATUS = 1000
258
+
259
+ $iError = _WinHttpWebSocketClose($hWebSocket , _
260
+ $WINHTTP_WEB_SOCKET_SUCCESS_CLOSE_STATUS )
261
+ If @error Or $iError <> 0 Then
262
+ ConsoleWrite (" WebSocketClose error" & @CRLF )
263
+ Return False
264
+ EndIf
265
+
266
+ ; Check close status returned by the server.
267
+
268
+ Local $iStatus = 0 , $iReasonLengthConsumed = 0
269
+ Local $tCloseReasonBuffer = DllStructCreate (" byte[123]" )
270
+
271
+ $iError = _WinHttpWebSocketQueryCloseStatus($hWebSocket , _
272
+ $iStatus , _
273
+ $iReasonLengthConsumed , _
274
+ $tCloseReasonBuffer )
275
+ If @error Or $iError <> 0 Then
276
+ ConsoleWrite (" QueryCloseStatus error" & @CRLF )
277
+ Return False
278
+ EndIf
279
+
280
+ ConsoleWrite (" The server closed the connection with status code: '" & $iStatus & " ' and reason: '" & _
281
+ BinaryToString (BinaryMid (DllStructGetData ($tCloseReasonBuffer , 1 ), 1 , $iReasonLengthConsumed )) & " '" & @CRLF )
282
+ EndFunc
283
+
284
+ Func _WinHttpSetOptionNoParams($hInternet , $iOption )
285
+ Local $aCall = DllCall ($hWINHTTPDLL__WINHTTP , " bool" , " WinHttpSetOption" , _
286
+ " handle" , $hInternet , " dword" , $iOption , " ptr" , 0 , " dword" , 0 )
287
+ If @error Or Not $aCall [0 ] Then Return SetError (4 , 0 , 0 )
288
+ Return 1
289
+ EndFunc ; ==>_WinHttpSetOptionNoParams
290
+
291
+ Func _WinHttpWebSocketCompleteUpgrade($hRequest , $pContext = 0 )
292
+ Local $aCall = DllCall ($hWINHTTPDLL__WINHTTP , " handle" , " WinHttpWebSocketCompleteUpgrade" , _
293
+ " handle" , $hRequest , _
294
+ " DWORD_PTR" , $pContext )
295
+ If @error Then Return SetError (@error , @extended , - 1 )
296
+ Return $aCall [0 ]
297
+ EndFunc ; ==>_WinHttpWebSocketCompleteUpgrade
298
+
299
+ Func _WinHttpWebSocketSend($hWebSocket , $iBufferType , $vData )
300
+ Local $tBuffer = 0 , $iBufferLen = 0
301
+ If IsBinary ($vData ) = 0 Then $vData = StringToBinary ($vData )
302
+ $iBufferLen = BinaryLen ($vData )
303
+ If $iBufferLen > 0 Then
304
+ $tBuffer = DllStructCreate (" byte[" & $iBufferLen & " ]" )
305
+ DllStructSetData ($tBuffer , 1 , $vData )
306
+ EndIf
307
+
308
+ Local $aCall = DllCall ($hWINHTTPDLL__WINHTTP , " DWORD" , " WinHttpWebSocketSend" , _
309
+ " handle" , $hWebSocket , _
310
+ " int" , $iBufferType , _
311
+ " ptr" , DllStructGetPtr ($tBuffer ), _
312
+ " DWORD" , $iBufferLen )
313
+ If @error Then Return SetError (@error , @extended , - 1 )
314
+ Return $aCall [0 ]
315
+ EndFunc ; ==>_WinHttpWebSocketSend
316
+
317
+ Func _WinHttpWebSocketReceive($hWebSocket , $tBuffer , ByRef $iBytesRead , ByRef $iBufferType )
318
+ Local $aCall = DllCall ($hWINHTTPDLL__WINHTTP , " handle" , " WinHttpWebSocketReceive" , _
319
+ " handle" , $hWebSocket , _
320
+ " ptr" , DllStructGetPtr ($tBuffer ), _
321
+ " DWORD" , DllStructGetSize ($tBuffer ), _
322
+ " DWORD*" , $iBytesRead , _
323
+ " int*" , $iBufferType )
324
+ If @error Then Return SetError (@error , @extended , - 1 )
325
+ $iBytesRead = $aCall [4 ]
326
+ $iBufferType = $aCall [5 ]
327
+ Return $aCall [0 ]
328
+ EndFunc ; ==>_WinHttpWebSocketReceive
329
+
330
+ Func _WinHttpWebSocketClose($hWebSocket , $iStatus , $tReason = 0 )
331
+ Local $aCall = DllCall ($hWINHTTPDLL__WINHTTP , " handle" , " WinHttpWebSocketClose" , _
332
+ " handle" , $hWebSocket , _
333
+ " USHORT" , $iStatus , _
334
+ " ptr" , DllStructGetPtr ($tReason ), _
335
+ " DWORD" , DllStructGetSize ($tReason ))
336
+ If @error Then Return SetError (@error , @extended , - 1 )
337
+ Return $aCall [0 ]
338
+ EndFunc ; ==>_WinHttpWebSocketClose
339
+
340
+ Func _WinHttpWebSocketQueryCloseStatus($hWebSocket , ByRef $iStatus , ByRef $iReasonLengthConsumed , $tCloseReasonBuffer = 0 )
341
+ Local $aCall = DllCall ($hWINHTTPDLL__WINHTTP , " handle" , " WinHttpWebSocketQueryCloseStatus" , _
342
+ " handle" , $hWebSocket , _
343
+ " USHORT*" , $iStatus , _
344
+ " ptr" , DllStructGetPtr ($tCloseReasonBuffer ), _
345
+ " DWORD" , DllStructGetSize ($tCloseReasonBuffer ), _
346
+ " DWORD*" , $iReasonLengthConsumed )
347
+ If @error Then Return SetError (@error , @extended , - 1 )
348
+ $iStatus = $aCall [2 ]
349
+ $iReasonLengthConsumed = $aCall [5 ]
350
+ Return $aCall [0 ]
351
+ EndFunc ; ==>_WinHttpWebSocketQueryCloseStatus
0 commit comments