Wake on lan WOL (Windows only)

Share your advanced PureBasic knowledge/code with the community.
ABBKlaus
Addict
Addict
Posts: 1143
Joined: Sat Apr 10, 2004 1:20 pm
Location: Germany

Wake on lan WOL (Windows only)

Post by ABBKlaus »

Hi,

this code sends a so called magic packet to a WOL capable pc on the network :

Code: Select all

; Author: ABBKlaus Dresen
; Date: 10. April 2004
; Modified: 15. November 2007
; PB4.xx compatible

InitNetwork()

Structure mac
  mac1.b[6]                                               ; MAC Adress is 6 Bytes long
EndStructure

Structure magic
  magic1.b[102]                                           ; Magic Packet 6x$FF 16xMAC = 102 Bytes
EndStructure

; Magig Packet Example :
; 
; FFFFFFFFFFFF <- Packet Header
; 000C6EB8CEEB <- 01. MAC Adress to wake up
; 000C6EB8CEEB <- 02. MAC Adress to wake up
; 000C6EB8CEEB <- 03. MAC Adress to wake up
; 000C6EB8CEEB <- 04. MAC Adress to wake up
; 000C6EB8CEEB <- 05. MAC Adress to wake up
; 000C6EB8CEEB <- 06. MAC Adress to wake up
; 000C6EB8CEEB <- 07. MAC Adress to wake up
; 000C6EB8CEEB <- 08. MAC Adress to wake up
; 000C6EB8CEEB <- 09. MAC Adress to wake up
; 000C6EB8CEEB <- 10. MAC Adress to wake up
; 000C6EB8CEEB <- 11. MAC Adress to wake up
; 000C6EB8CEEB <- 12. MAC Adress to wake up
; 000C6EB8CEEB <- 13. MAC Adress to wake up
; 000C6EB8CEEB <- 14. MAC Adress to wake up
; 000C6EB8CEEB <- 15. MAC Adress to wake up
; 000C6EB8CEEB <- 16. MAC Adress to wake up

Procedure.s WOL_Storemac(macadress$,*mac_adress.mac)
  Protected pointer1.b=0
  Protected pointer2.b=0
  Protected value.b=0
  Protected tmac.l=0
  Protected wert.l=0
  Protected a$=""
  
  For i=1 To Len(macadress$)
    a$=Mid(macadress$,i,1)
    value=0
    If a$>="0" And a$=<"9"
      wert=Asc(a$)-48
      value=1
    EndIf
    If a$>="a" And a$=<"f"
      wert=Asc(a$)-87
      value=1
    EndIf
    If a$>="A" And a$=<"F"
      wert=Asc(a$)-55
      value=1
    EndIf
    If value = 1
      If pointer1=0
        tmac=tmac+wert*16
      Else
        tmac=tmac+wert
      EndIf
      pointer1+1
      If pointer1>1
        *mac_adress\mac1[pointer2]=tmac
        pointer1=0
        pointer2+1
        tmac=0
      EndIf
    EndIf
  Next
EndProcedure

Procedure.l WOL_SendMagicPacket(macadress$,client_ip.s="255.255.255.255")
  Protected mac_adress.mac
  Protected Success.l=0
  Protected client_bip.l
  Protected client_port.l
  Protected client_bport.w
  Protected client_socket.l
  Protected socket_keepalive.b
  Protected server_mode.l
  Protected magic_packet.magic
  
  WOL_Storemac(macadress$,@mac_adress)
  
  For j=0 To 16
    debugmac$=""
    For i=0 To 5
      If j=0
        magic_packet.magic\magic1[i+j*6] = 255
      Else
        magic_packet.magic\magic1[i+j*6] = mac_adress.mac\mac1[i]
      EndIf
      debugmac$+RSet(Hex(magic_packet.magic\magic1[i+j*6]),3,"00 ")
    Next
    Debug RSet(Hex(j*6),2,"0")+":"+debugmac$
  Next
  
  client_bip = inet_addr_(client_ip)
  client_port = 0
  client_bport = htons_(client_port) ; convert to long
  client_socket = SOCKET_(#AF_INET, #SOCK_DGRAM, #IPPROTO_UDP) ; create the socket
  If client_socket
    socket_keepalive = 1
    If setsockopt_(client_socket, #SOL_SOCKET, #SO_BROADCAST, @socket_keepalive, 1) = 0
      client_sockaddr.SOCKADDR_IN
      client_sockaddr\sin_family = #AF_INET
      client_sockaddr\sin_port = client_bport
      client_sockaddr\sin_addr = client_bip
      server_mode = 0
      If ioctlsocket_(client_socket,#FIONBIO,@server_mode) = 0
        send.l = sendto_(client_socket, @magic_packet, SizeOf(magic_packet), 0, @client_sockaddr, 16)
        If send=SizeOf(magic_packet) And WSAGetLastError_()=0
          Debug "Magic packet send"
          Success=1
        EndIf
      EndIf
    EndIf
    
    closesocket_(client_socket)
  EndIf
  
  ProcedureReturn Success
EndProcedure

If OpenWindow(0, 245, 73, 296, 110, "Wake on Lan", #PB_Window_SystemMenu | #PB_Window_TitleBar | #PB_Window_ScreenCentered)
  If CreateGadgetList(WindowID(0))
    TextGadget(1, 7, 10, 83, 20, "Broadcast")
    TextGadget(2, 7, 40, 83, 20, "Target-MAC") 
    StringGadget(3, 100, 10, 190, 20, "255.255.255.255")
    StringGadget(4, 100, 40, 190, 20, "00-00-00-00-00-00") 
    ButtonGadget(5, 190, 70, 100, 30, "Send") 
  EndIf
EndIf

Repeat
  
  Event = WaitWindowEvent()
  
  If Event = #PB_Event_Gadget
    If EventGadget() = 5
      TargetAddress$ = GetGadgetText(3)
      TargetMAC$ = GetGadgetText(4)
      If TargetAddress$
        WOL_SendMagicPacket(TargetMAC$,TargetAddress$)
      Else
        WOL_SendMagicPacket(TargetMAC$)
      EndIf
    EndIf
  EndIf 
  
Until Event = #PB_Event_CloseWindow

End
User avatar
Rook Zimbabwe
Addict
Addict
Posts: 4326
Joined: Tue Jan 02, 2007 8:16 pm
Location: Cypress TX
Contact:

Post by Rook Zimbabwe »

This is great ABB... but my query is can you also to arrange to send a SHUT DOWN order to a LAN machine???

Cybercafe software question! :D
Binarily speaking... it takes 10 to Tango!!!

Image
http://www.bluemesapc.com/
ABBKlaus
Addict
Addict
Posts: 1143
Joined: Sat Apr 10, 2004 1:20 pm
Location: Germany

Post by ABBKlaus »

Rook Zimbabwe wrote:This is great ABB... but my query is can you also to arrange to send a SHUT DOWN order to a LAN machine???

Cybercafe software question! :D
i don´t want to reinvent the wheel :roll:

Here´s a link that should bring you where you want to go today :arrow: http://www.microsoft.com/technet/sysint ... tdown.mspx

PS : you can´t logoff a computer where you don´t have the rights :!:
User avatar
Psychophanta
Addict
Addict
Posts: 4997
Joined: Wed Jun 11, 2003 9:33 pm
Location: Lípetsk, Russian Federation
Contact:

Post by Psychophanta »

Thanks for that!
http://www.zeitgeistmovie.com

While world=business:world+mafia:Wend
Will never leave this forum until the absolute bugfree PB :mrgreen:
delta69
User
User
Posts: 15
Joined: Fri Apr 25, 2003 10:56 pm

Post by delta69 »

Hello,

On recent Windows versions (Vista, XP, maybe 2K), you can use the shutdown.exe command (located in the system32 directory) with /m switch to specify a remote computer.

Regards,
Nicolas
User avatar
Psychophanta
Addict
Addict
Posts: 4997
Joined: Wed Jun 11, 2003 9:33 pm
Location: Lípetsk, Russian Federation
Contact:

Post by Psychophanta »

delta69 wrote:Hello,

On recent Windows versions (Vista, XP, maybe 2K), you can use the shutdown.exe command (located in the system32 directory) with /m switch to specify a remote computer.

Regards,
Nicolas
Yeah, the hard thing is to wake up. To asleep is easy :P
http://www.zeitgeistmovie.com

While world=business:world+mafia:Wend
Will never leave this forum until the absolute bugfree PB :mrgreen:
User avatar
thyphoon
Enthusiast
Enthusiast
Posts: 327
Joined: Sat Dec 25, 2004 2:37 pm

Post by thyphoon »

In don't know is you know this free tools :
beyondexeV2 it 's a very great software to shutdown, reset or send an executable to a another computer on network
http://www.beyondlogic.org/solutions/re ... ndExec.htm

:D
User avatar
thyphoon
Enthusiast
Enthusiast
Posts: 327
Joined: Sat Dec 25, 2004 2:37 pm

Post by thyphoon »

Hello
Do you know how to read Mac Address with Purebasic when we know the Computer's IP ?
dell_jockey
Enthusiast
Enthusiast
Posts: 767
Joined: Sat Jan 24, 2004 6:56 pm

Post by dell_jockey »

thyphoon wrote:Hello
Do you know how to read Mac Address with Purebasic when we know the Computer's IP ?
Ping that IP and read the ARP-cache table directly afterwards.
- on Windows you open a cmd-box and type: 'arp -s'
- in a Linux shell I seem to remember it's 'arp -a', but I'm not quite sure about this.
Last edited by dell_jockey on Fri Dec 07, 2007 11:07 am, edited 2 times in total.
cheers,
dell_jockey
________
http://blog.forex-trading-ideas.com
User avatar
thyphoon
Enthusiast
Enthusiast
Posts: 327
Joined: Sat Dec 25, 2004 2:37 pm

Post by thyphoon »

dell_jockey wrote:
thyphoon wrote:Hello
Do you know how to read Mac Address with Purebasic when we know the Computer's IP ?
ping that IP and read the ARP-cache table directly afterwards. On Windows you open a cmd-box and type: 'arp -s'
Thanks a lot !! :D
ABBKlaus
Addict
Addict
Posts: 1143
Joined: Sat Apr 10, 2004 1:20 pm
Location: Germany

Post by ABBKlaus »

User avatar
thyphoon
Enthusiast
Enthusiast
Posts: 327
Joined: Sat Dec 25, 2004 2:37 pm

Post by thyphoon »

Thanks it's great !! :o)
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6161
Joined: Sat May 17, 2003 11:31 am
Contact:

Re: Wake on lan WOL (Windows only)

Post by blueznl »

I noticed the old example would not work. Here's my take.

Code: Select all

InitNetwork()

Procedure.i x_pokehex(addr.i,s.s)                                    ; write a hex sequence to memory
  Protected l.i, n.i, p.i, x.s, v.i
  ;
  l = Len(s)
  p = 0
  ;
  While n+1 < l
    n = n+1
    x = Mid(s,n,1)
    If ( x >= "0" And x <= "9" ) Or ( x >= "A" And x <= "F" ) Or ( x >= "a" And x <= "f" )
      x = Mid(s,n+1,1)
      If ( x >= "0" And x <= "9" ) Or ( x >= "A" And x <= "F" ) Or ( x >= "a" And x <= "f" )
        v = Val("$"+Mid(s,n,2))
        n = n+1
        PokeB(addr+p,v)
        p = p+1
      EndIf
    EndIf
  Wend
  ;
  ProcedureReturn p
EndProcedure


Procedure.i x_wol(mac.s, ip.s="255.255.255.255", port.l=0)                                   ; send magic packet (wakeonlan)
  Protected p.i, n.i
  Protected bip.l, bport.w, socket.l, keepalive.b, servermode.l, sockaddr.SOCKADDR_IN, send.i
  Protected Dim magicpacket.b(102)
  ;
  ; *** send a magic packet to another computer
  ;
  ; notes
  ;
  ; - need to call either InitNetwork() or x_ws_start() before calling this procedure
  ; - specifying port and IP might be useful on WAN's but for LAN's just broadcast to 255.255.255.255:0
  ; 
  ; build the magic packet
  ;
  p = @magicpacket(0)
  ;
  ; header is 16 bytes $FF
  ;
  x_pokehex(p, "$ FF FF FF FF FF FF")
  ;
  ; followed by 16x mac address
  ;
  For n = 1 To 16
    x_pokehex(p+n*6,mac)
  Next n
  ;
  ; open a socket and send the message
  ;
  x_retval = 0
  ;
  socket     = SOCKET_(#AF_INET, #SOCK_DGRAM, #IPPROTO_UDP)
  If socket
    keepalive  = 1
    If setsockopt_(socket, #SOL_SOCKET, #SO_BROADCAST, @keepalive, 1) = 0
      sockaddr.SOCKADDR_IN
      sockaddr\sin_family = #AF_INET
      sockaddr\sin_port   = htons_(port)
      sockaddr\sin_addr   = inet_addr_(ip)
      servermode = 0
      If ioctlsocket_(socket,#FIONBIO,@servermode) = 0
        send = sendto_(socket, p, 102, 0, @sockaddr, 16)
        If send=102 And WSAGetLastError_()=0
          x_retval = 1
        EndIf
      EndIf
    EndIf
    closesocket_(socket)
  EndIf
  ;
  ProcedureReturn x_retval
EndProcedure

x_wol("bc-5f-f4-12-06-9e")
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
GPI
PureBasic Expert
PureBasic Expert
Posts: 1394
Joined: Fri Apr 25, 2003 6:41 pm

Re: Wake on lan WOL (Windows only)

Post by GPI »

I updated the code for Win64 + Unicode:
https://github.com/GPIforGit/PureBasic- ... eOnLan.pbi
User avatar
Michael Vogel
Addict
Addict
Posts: 2680
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Wake on lan WOL (Windows only)

Post by Michael Vogel »

The github link does not work :?

Anyhow, the code from ABBKlaus is quite fine - just compressed it a little bit (see below)...
...but I have a small problem, how to control on which network interface the broadcast will be sent? I have a PC which has two ethernet NIC's and the magic packet is sent on the wrong one (as expected) :evil:

Code: Select all

EnableExplicit

InitNetwork()

; Magig Packet Example :
; FFFFFFFFFFFF <- Packet Header
; 0123456789AB <- 01. MAC Adress to wake up
; 0123456789AB <- 02. MAC Adress to wake up
;       :
; 0123456789AB <- 16. MAC Adress to wake up

Structure MacType;				MAC-Adresse in Byte-Darstellung
	Byte.b[6]
EndStructure

Structure MagicType;			Magic Packet ( 6 $FF-Bytes + 16 MAC-Adressen, welche aufgeweckt werden sollen)
	Byte.b[102]
EndStructure

#MacStringBytes=17;				6x2 Ziffern + 5 Trennzeichen (00-00-00-00-00-00)

Procedure MACtoStructure(s.s,*v.MacType)

	Protected i

	If Len(s)-#MacStringBytes
		s="00-00-00-00-00-00"
	EndIf

	For i=0 To 5
		*v\Byte[i]=Val("$"+Mid(s,i*3+1,2))
	Next i

EndProcedure

Procedure.l WOL_SendMagicPacket(mac.s,ip.s="255.255.255.255")

	Protected mac_adress.MacType
	Protected Success.l=0
	Protected client_bip.l
	Protected client_port.l
	Protected client_bport.w
	Protected client_socket.l
	Protected socket_keepalive.b
	Protected server_mode.l
	Protected magic_packet.MagicType

	Protected client_sockaddr.SOCKADDR_IN
	Protected send.l

	Protected i,j
	Protected showmac.s

	MACtoStructure(mac,mac_adress)

	For j=0 To 16
		showmac=""
		For i=0 To 5
			If j=0
				magic_packet\Byte[i+j*6] = 255
			Else
				magic_packet\Byte[i+j*6] = mac_adress\Byte[i]
			EndIf
			showmac+RSet(Hex(magic_packet\Byte[i+j*6]),3,"00 ")
		Next
		Debug RSet(Hex(j*6),2,"0")+": "+showmac
	Next

	client_bip = inet_addr_(ip)
	client_port = 0
	client_bport = htons_(client_port) ; convert to long
	client_socket = SOCKET_(#AF_INET, #SOCK_DGRAM, #IPPROTO_UDP) ; create the socket
	If client_socket
		socket_keepalive = 1
		If setsockopt_(client_socket, #SOL_SOCKET, #SO_BROADCAST, @socket_keepalive, 1) = 0

			client_sockaddr\sin_family = #AF_INET
			client_sockaddr\sin_port = client_bport
			client_sockaddr\sin_addr = client_bip
			server_mode = 0
			If ioctlsocket_(client_socket,#FIONBIO,@server_mode) = 0
				send.l = sendto_(client_socket, @magic_packet, SizeOf(magic_packet), 0, @client_sockaddr, 16)
				If send=SizeOf(magic_packet) And WSAGetLastError_()=0
					Debug "Magic packet send"
					Success=1
				EndIf
			EndIf
		EndIf

		closesocket_(client_socket)
	EndIf

	ProcedureReturn Success

EndProcedure

WOL_SendMagicPacket("01:02:03:04:05:FF")
Post Reply