diff --git a/client/tests/kvm/deps/finish.cpp b/client/tests/kvm/deps/finish.cpp
index e5ba128..3fbbeeb 100644
--- a/client/tests/kvm/deps/finish.cpp
+++ b/client/tests/kvm/deps/finish.cpp
@@ -9,11 +9,9 @@
 
 // Usage: finish.exe
 
-// 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
+#define _WIN32_WINNT 0x500
 #endif
 
 #include <windows.h>
@@ -22,7 +20,75 @@
 #include <stdlib.h>
 #include <stdio.h>
 
-#define DEFAULT_PORT "12323"
+int DEFAULT_PORT = 12323;
+HWND hMainWindow = NULL;
+
+void ExitOnError(const char *message, BOOL winsock = FALSE)
+{
+    LPVOID system_message;
+    char buffer[512];
+    int error_code;
+
+    if (winsock)
+        error_code = WSAGetLastError();
+    else
+        error_code = GetLastError();
+    WSACleanup();
+
+    FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
+                  FORMAT_MESSAGE_FROM_SYSTEM,
+                  NULL,
+                  error_code,
+                  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                  (LPTSTR)&system_message,
+                  0,
+                  NULL);
+
+    sprintf(buffer,
+            "%s!\n"
+            "Error code = %d\n"
+            "Error message = %s",
+            message, error_code, (char *)system_message);
+
+    MessageBox(hMainWindow, buffer, "Error", MB_OK | MB_ICONERROR);
+
+    LocalFree(system_message);
+    ExitProcess(1);
+}
+
+SOCKET PrepareListenSocket(int port)
+{
+    sockaddr_in addr;
+    linger l;
+    int result;
+
+    // Create socket
+    SOCKET ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+    if (ListenSocket == INVALID_SOCKET)
+        ExitOnError("Socket creation failed", TRUE);
+
+    // Enable lingering
+    l.l_linger = 10;
+    l.l_onoff = 1;
+    setsockopt(ListenSocket, SOL_SOCKET, SO_LINGER, (char *)&l, sizeof(l));
+
+    // Bind the socket
+    addr.sin_family = AF_INET;
+    addr.sin_addr.s_addr = htonl(INADDR_ANY);
+    addr.sin_port = htons(port);
+
+    result = bind(ListenSocket, (sockaddr *)&addr, sizeof(addr));
+    if (result == SOCKET_ERROR)
+        ExitOnError("Bind failed", TRUE);
+
+    // Start listening for incoming connections
+    result = listen(ListenSocket, SOMAXCONN);
+    if (result == SOCKET_ERROR)
+        ExitOnError("Listen failed", TRUE);
+
+    return ListenSocket;
+}
+
 int main(int argc, char **argv)
 {
     WSADATA wsaData;
@@ -33,15 +99,13 @@ int main(int argc, char **argv)
 
     // Validate the parameters
     if (argc != 1) {
-        printf("usage: %s", argv[0]);
-        return 1;
+        ExitOnError("Finish.exe takes no parameters", FALSE);
     }
 
     // Initialize Winsock
     iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
     if (iResult != 0) {
-        printf("WSAStartup failed: %d\n", iResult);
-        return 1;
+        ExitOnError("WSAStartup failed", FALSE);
     }
 
     ZeroMemory(&hints, sizeof(hints));
@@ -51,50 +115,19 @@ int main(int argc, char **argv)
     hints.ai_flags = AI_PASSIVE;
 
     // Resolve the server address and port
-    iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
-    if (iResult != 0) {
-        printf("getaddrinfo failed: %d\n", iResult);
-        WSACleanup();
-        return 1;
-    }
-
-    // Create a SOCKET for connecting to server
-    ListenSocket = socket(result->ai_family, result->ai_socktype,
-                          result->ai_protocol);
-    if (ListenSocket == INVALID_SOCKET) {
-        printf("socket failed: %ld\n", WSAGetLastError());
-        freeaddrinfo(result);
-        WSACleanup();
-        return 1;
-    }
-
-    // Setup the TCP listening socket
-    iResult = bind(ListenSocket, result->ai_addr, (int)result->ai_addrlen);
-    if (iResult == SOCKET_ERROR) {
-        printf("bind failed: %d\n", WSAGetLastError());
-        freeaddrinfo(result);
-        closesocket(ListenSocket);
-        WSACleanup();
-        return 1;
-    }
-
-    freeaddrinfo(result);
+    ListenSocket = PrepareListenSocket(DEFAULT_PORT);
 
     iResult = listen(ListenSocket, SOMAXCONN);
     if (iResult == SOCKET_ERROR) {
-        printf("listen failed: %d\n", WSAGetLastError());
         closesocket(ListenSocket);
-        WSACleanup();
-        return 1;
+        ExitOnError("Listen failed", TRUE);
     }
 
     // Accept a client socket
     ClientSocket = accept(ListenSocket, NULL, NULL);
     if (ClientSocket == INVALID_SOCKET) {
-        printf("accept failed: %d\n", WSAGetLastError());
         closesocket(ListenSocket);
-        WSACleanup();
-        return 1;
+        ExitOnError("Accept failed", TRUE);
     }
 
     // No longer need the server socket
@@ -103,10 +136,8 @@ int main(int argc, char **argv)
     // Send the ack string to the client
     iSendResult = send(ClientSocket, sendbuf, sizeof(sendbuf), 0);
     if (iSendResult == SOCKET_ERROR) {
-        printf("send failed: %d\n", WSAGetLastError());
         closesocket(ClientSocket);
-        WSACleanup();
-        return 1;
+        ExitOnError("Send failed", TRUE);
     }
     // Report the number of bytes sent
     printf("Bytes sent: %d\n", iSendResult);
@@ -114,10 +145,8 @@ int main(int argc, char **argv)
     // Shutdown the connection since we're done
     iResult = shutdown(ClientSocket, SD_SEND);
     if (iResult == SOCKET_ERROR) {
-        printf("shutdown failed: %d\n", WSAGetLastError());
         closesocket(ClientSocket);
-        WSACleanup();
-        return 1;
+        ExitOnError("Shutdown failed", TRUE);
     }
 
     // Cleanup
diff --git a/client/tests/kvm/tests_base.cfg.sample b/client/tests/kvm/tests_base.cfg.sample
index c678898..47266d9 100644
--- a/client/tests/kvm/tests_base.cfg.sample
+++ b/client/tests/kvm/tests_base.cfg.sample
@@ -1097,6 +1097,12 @@ variants:
                     user = user
                 setup:
                     steps = Win2000-32-rss.steps
+                unattended_install.cdrom:
+                    cdrom = windows/Windows2000_sp4.iso
+                    md5sum = dda6039f3a9173f0f6bfae40f5efdfea
+                    md5sum_1m = dd28fba196d366d56fe774bd93df5527
+                    unattended_file = unattended/win2000-32.sif
+                    floppy = images/win2000-32/floppy.img
 
             - WinXP:
                 image_name = winXP
diff --git a/client/tests/kvm/unattended/win2000-32.sif b/client/tests/kvm/unattended/win2000-32.sif
new file mode 100644
index 0000000..7562846
--- /dev/null
+++ b/client/tests/kvm/unattended/win2000-32.sif
@@ -0,0 +1,73 @@
+;SetupMgrTag
+[Data]
+    AutoPartition=1
+    MsDosInitiated="0"
+    UnattendedInstall="Yes"
+
+[Unattended]
+    Repartition=Yes
+    UnattendMode=FullUnattended
+    OemSkipEula=Yes
+    OemPreinstall=No
+    TargetPath=\WINDOWS
+    UnattendSwitch=Yes
+    CrashDumpSetting=1
+    DriverSigningPolicy=ignore
+    WaitForReboot=no
+
+[GuiUnattended]
+    AdminPassword="1q2w3eP"
+    EncryptedAdminPassword=NO
+    TimeZone=85
+    OemSkipWelcome=1
+    AutoLogon=Yes
+    AutoLogonCount=1000
+    OEMSkipRegional=1
+
+[UserData]
+    ProductKey=KVM_TEST_CDKEY
+    FullName="Autotest Mindless Drone"
+    OrgName="Autotest"
+    ComputerName=*
+
+[Identification]
+    JoinWorkgroup=WORKGROUP
+
+[Networking]
+    InstallDefaultComponents=Yes
+
+[Proxy]
+    Proxy_Enable=0
+    Use_Same_Proxy=0
+
+[Components]
+    dialer=off
+    media_clips=off
+    media_utopia=off
+    msnexplr=off
+    netoc=off
+    OEAccess=off
+    templates=off
+    WMAccess=off
+    zonegames=off
+
+[TerminalServices]
+    AllowConnections=1
+
+[WindowsFirewall]
+    Profiles=WindowsFirewall.TurnOffFirewall
+
+[WindowsFirewall.TurnOffFirewall]
+    Mode=0
+
+[Branding]
+    BrandIEUsingUnattended=Yes
+
+[Display]
+    Xresolution=1024
+    YResolution=768
+
+[GuiRunOnce]
+   Command0="cmd /c E:\setuprss.bat"
+   Command1="cmd /c netsh interface ip set address local dhcp"
+   Command2="cmd /c ping 10.0.2.2 -n 20 && A:\finish.exe"
