Realized that the unattended install mechanism could work just fine for win2000. After some thinkering, verified that finish.exe needed some changes to make it work with windows versions prior to winXP. Inspired on code from rss.exe, made finish.exe work in older windows systems, also included a new win2000 unattended install file. The new finish.exe executable will be added only when this patch is going to be commited, to avoid binary diffs sent to the list. Signed-off-by: Lucas Meneghel Rodrigues <lmr@xxxxxxxxxx> --- client/tests/kvm/deps/finish.cpp | 125 +++++++++++++++++----------- client/tests/kvm/tests_base.cfg.sample | 6 ++ client/tests/kvm/unattended/win2000-32.sif | 73 ++++++++++++++++ 3 files changed, 156 insertions(+), 48 deletions(-) create mode 100644 client/tests/kvm/unattended/win2000-32.sif 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" -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html