#include #include #include #include #include "splash.h" #include "bmputil.h" // define the magic value used in GetWinFlags to show that this application // is running on a Windows NT box in 16-bit emulation mode. #define WF_WINNT 0x4000 #define MAX_PATH 256 #ifdef _WIN32 int GetWinFlags() { return 0; } #endif HWND app_window; HINSTANCE app_instance; char * app_cmdLine; typedef void (* splashfn) (HINSTANCE a, unsigned int time); typedef HBITMAP (* bmploadfn) (HDC device, LPSTR name); typedef struct { BYTE majorVersion; BYTE minorVersion; WORD buildNumber; BOOL debug; } win32sInfo, FAR * lpWin32sInfo; typedef enum { Windows2x, Windows3_0x, Windows3_1x, Windows9x, WindowsNT } gs16PlatformId; typedef struct { gs16PlatformId platform; bool win32s; } gs16PlatformInfo; typedef int (FAR PASCAL * win32sInfoFn)(lpWin32sInfo); bool appendPath(char *original, char *extension, int maxlen) { int extralen = 0; if (original[strlen(original) - 1] != '\\') { extralen ++; } if (extension[0] == '\\') { extralen --; } if (strlen(original) + strlen(extension) + extralen + 1 > maxlen) { return false; } if (extralen > 0) { strcat(original, "\\"); } else if (extralen < 0) { extension ++; } strcat(original,extension); return true; } /** * Function called before attempting a LoadModule as that call reports * an error if w32sys.dll doesn't exist */ bool GS16bit_checkExistsWin32s() { char buffer[MAX_PATH]; OFSTRUCT of; if (GetSystemDirectory(buffer, MAX_PATH) == 0) { return true; } if (!appendPath(buffer, "win32s\\w32sys.dll", MAX_PATH)) { return FALSE; } strcpy(buffer, "win32s\\w32.dll"); if (OpenFile((LPCSTR) buffer, (LPOFSTRUCT) &of, OF_EXIST) == HFILE_ERROR) { // try system directory directly; no need to error check - we know that // we don't have a length problem GetSystemDirectory(buffer, MAX_PATH); appendPath(buffer, "w32sys.dll", MAX_PATH); // if it isn't there either, return false if (OpenFile((LPCSTR) buffer, (LPOFSTRUCT) &of, OF_EXIST) == HFILE_ERROR) { return false; } } return true; } bool GS16bit_checkForWin32s() { HINSTANCE w32sHandle; win32sInfoFn infoFnPtr; win32sInfo w32sInfo; bool reply = false; // check if the module exists if (GS16bit_checkExistsWin32s() == true) { w32sHandle = LoadLibrary("W32SYS.DLL"); } else { w32sHandle = NULL; } // try to get a handle onto the win32s library if (w32sHandle != NULL) { // now get the address of the GetWin32sInfo function infoFnPtr = (win32sInfoFn) GetProcAddress(w32sHandle, "GETWIN32SINFO"); // if the function exists, we've got win32s1.1 or later if (infoFnPtr != NULL) { if ((*infoFnPtr)((lpWin32sInfo) &w32sInfo) == 0) // no error state { reply = true; } else // error - call didn't work; assume that we have a non-functional // win32s { reply = false; } } // else we've got win32s 1.0. TODO: We need to check if it's actually up and // running; else { reply = true; } // we need to free the library before finishing this function FreeLibrary(w32sHandle); } // no win32s at all else { reply = false; } return reply; } void GS16bit_getPlatformInfo(gs16PlatformInfo &info) { DWORD version = GetVersion(); /** * NB: Ignore ALL standard information on using GetVersion in the * standard Windows 3.1 SDK and Windows 32-bit SDK documentation; * the latter does not apply, and the former is (slightly but signif- * cantly) misdocumented. * * On 16-bit windows (i.e. this program) take the following comments * as gospel. Also refer to * * http://support.microsoft.com/support/kb/articles/Q131/3/71.asp */ BYTE majorVersion = LOBYTE(LOWORD(version)); BYTE minorVersion = HIBYTE(LOWORD(version)); BYTE dosVersion = HIBYTE(HIWORD(version)); if (majorVersion < 3) { info.platform = Windows2x; } else if (majorVersion == 3 && minorVersion >= 95) // it's Windows 95 from the // minor version; I guess that // 98 may have minor version == 98, // but I don't know! Hence the // cautious check { info.platform = Windows9x; } else // we're running in "some sort" of Windows 3.x environment { if (minorVersion == 10 && dosVersion == 5) // it could be running under WOW // (16-bit Windows emulation in // Windows NT) { if ((GetWinFlags() & WF_WINNT) == WF_WINNT) // check for NT in emulation mode { info.platform = WindowsNT; } else { info.platform = Windows3_1x; } } else if (minorVersion >= 10) // perhaps Windows 3.11 { info.platform = Windows3_1x; } else { info.platform = Windows3_0x; } } if (info.platform == Windows3_1x) { info.win32s = GS16bit_checkForWin32s(); } else { info.win32s = false; } } void GS16bit_checkWindowsVersion() { gs16PlatformInfo platformInfo; GS16bit_getPlatformInfo(platformInfo); if (platformInfo.platform == Windows3_0x || platformInfo.platform == Windows2x) { MessageBox(app_window, "Greenstone cannot be installed on this computer. It requires " "Windows 3.10 or later", "Greenstone Installer", MB_OK); } else if ( platformInfo.platform == Windows3_1x && platformInfo.win32s == false) { int result; MessageBox(app_window, "Greenstone requires 32 bit Windows. Win32s will now be installed " "on your computer to provide this, before continuing with the main " "installation.", "Greenstone Installer", MB_OK); result = WinExec("win32s\\setup.exe", SW_SHOWNORMAL); } else { char buffer[20]; int result; /* MessageBox(app_window, "Greenstone will now install", "Greenstone Installer", MB_OK);*/ result = WinExec("gssetup.exe", SW_SHOWNORMAL); } } long FAR PASCAL GS16bitWindProc(HWND Window, WORD Message, WPARAM wParameter, LPARAM lParameter) { long reply = 0; switch(Message) { case WM_CREATE: { } break; case WM_COMMAND: break; case WM_CLOSE: DestroyWindow(Window); return 0L; case WM_DESTROY: { PostQuitMessage(0); } break; default: return(DefWindowProc(Window, Message, wParameter, lParameter)); } return reply; } void GS16bit_init(HINSTANCE instance, int Show) { FARPROC showsplash; FARPROC loadbmp; HDC dc; char buffer[20]; /* dc = GetDC(GetDesktopWindow()); bmpUtil_loadBitmap(dc, "C:\\gs.bmp"); ReleaseDC(GetDesktopWindow(), dc); */ // showsplash = MakeProcInstance((FARPROC) splash_show, instance); // (*(splashfn) showsplash)(instance, 3000); GS16bit_checkWindowsVersion(); app_window = CreateWindow("GS16bit:Main", "GreenStone Installer", WS_OVERLAPPEDWINDOW | WS_MINIMIZE | CS_DBLCLKS, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, app_instance, NULL); ShowWindow(app_window, Show); PostQuitMessage(0); } void WinClassInit(void) { WNDCLASS Class; Class.lpszClassName = "GS16bit:Main"; Class.hInstance = app_instance; Class.lpfnWndProc = (WNDPROC) GS16bitWindProc; Class.hCursor = LoadCursor(NULL, IDC_ARROW); Class.hIcon = NULL; //LoadIcon(app_instance, "GSInstall"); Class.lpszMenuName = NULL; Class.hbrBackground = (HBRUSH) (COLOR_APPWORKSPACE+1); Class.style = NULL; Class.cbClsExtra = 0; Class.cbWndExtra = 0; RegisterClass(&Class); } int PASCAL WinMain(HINSTANCE Current, HINSTANCE Previous, LPSTR CmdLine, int CmdShow) { MSG msg; app_cmdLine = (char *) LocalAlloc(LMEM_FIXED, lstrlen(CmdLine) + 1); lstrcpy(app_cmdLine, CmdLine); app_instance = Current; /* -- init application */ if (!Previous) { WinClassInit(); } /* -- init instance */ GS16bit_init(Current, CmdShow); while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int) msg.wParam; }