new file mode 100644
@@ -0,0 +1,121 @@
+// Simple app that only sends an ack string to the KVM unattended install
+// watch code.
+//
+// You must link this code with Ws2_32.lib, Mswsock.lib, and Advapi32.lib
+//
+// Author: Lucas Meneghel Rodrigues <lmr@redhat.com>
+// Code was adapted from an MSDN sample.
+
+// Usage: finish.exe [Host OS IP]
+
+// MinGW's ws2tcpip.h only defines getaddrinfo and other functions only for
+// the case _WIN32_WINNT >= 0x0501.
+#ifdef __MINGW32__
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x501
+#endif
+
+#include <windows.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define DEFAULT_BUFLEN 512
+#define DEFAULT_PORT "12323"
+
+int main(int argc, char **argv)
+{
+ WSADATA wsaData;
+ SOCKET ConnectSocket = INVALID_SOCKET;
+ struct addrinfo *result = NULL,
+ *ptr = NULL,
+ hints;
+ char *sendbuf = "done";
+ char recvbuf[DEFAULT_BUFLEN];
+ int iResult;
+ int recvbuflen = DEFAULT_BUFLEN;
+
+ // Validate the parameters
+ if (argc != 2) {
+ printf("usage: %s server-name\n", argv[0]);
+ return 1;
+ }
+
+ // Initialize Winsock
+ iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
+ if (iResult != 0) {
+ printf("WSAStartup failed: %d\n", iResult);
+ return 1;
+ }
+
+ ZeroMemory( &hints, sizeof(hints) );
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+
+ // Resolve the server address and port
+ iResult = getaddrinfo(argv[1], DEFAULT_PORT, &hints, &result);
+ if ( iResult != 0 ) {
+ printf("getaddrinfo failed: %d\n", iResult);
+ WSACleanup();
+ return 1;
+ }
+
+ // Attempt to connect to an address until one succeeds
+ for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {
+
+ // Create a SOCKET for connecting to server
+ ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
+ ptr->ai_protocol);
+ if (ConnectSocket == INVALID_SOCKET) {
+ printf("Error at socket(): %ld\n", WSAGetLastError());
+ freeaddrinfo(result);
+ WSACleanup();
+ return 1;
+ }
+
+ // Connect to server.
+ iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
+ if (iResult == SOCKET_ERROR) {
+ closesocket(ConnectSocket);
+ ConnectSocket = INVALID_SOCKET;
+ continue;
+ }
+ break;
+ }
+
+ freeaddrinfo(result);
+
+ if (ConnectSocket == INVALID_SOCKET) {
+ printf("Unable to connect to server!\n");
+ WSACleanup();
+ return 1;
+ }
+
+ // Send the ACK buffer
+ iResult = send( ConnectSocket, sendbuf, (int)strlen(sendbuf), 0 );
+ if (iResult == SOCKET_ERROR) {
+ printf("send failed: %d\n", WSAGetLastError());
+ closesocket(ConnectSocket);
+ WSACleanup();
+ return 1;
+ }
+
+ printf("Bytes Sent: %ld\n", iResult);
+
+ // shutdown the connection since no more data will be sent
+ iResult = shutdown(ConnectSocket, SD_SEND);
+ if (iResult == SOCKET_ERROR) {
+ printf("shutdown failed: %d\n", WSAGetLastError());
+ closesocket(ConnectSocket);
+ WSACleanup();
+ return 1;
+ }
+
+ // cleanup
+ closesocket(ConnectSocket);
+ WSACleanup();
+
+ return 0;
+}