1 /* Copyright (C) 2001 by Alex Kompel <shurikk@pacbell.net> */
2 /* NetHack may be freely redistributed.  See license for details. */
3 
4 // winhack.cpp : Defines the entry point for the application.
5 //
6 
7 #include <process.h>
8 #include "winMS.h"
9 #include "hack.h"
10 #include "dlb.h"
11 #include "resource.h"
12 #include "mhmain.h"
13 #include "mhmap.h"
14 
15 #if !defined(__BORLANDC__) && !defined(__MINGW32__)
16 #include <shlwapi.h>
17 #else /* Borland redefines "boolean" in shlwapi.h so just use the little bit we need */
18 typedef struct _DLLVERSIONINFO
19 {
20     DWORD cbSize;
21     DWORD dwMajorVersion;                   // Major version
22     DWORD dwMinorVersion;                   // Minor version
23     DWORD dwBuildNumber;                    // Build number
24     DWORD dwPlatformID;                     // DLLVER_PLATFORM_*
25 } DLLVERSIONINFO;
26 
27 //
28 // The caller should always GetProcAddress("DllGetVersion"), not
29 // implicitly link to it.
30 //
31 
32 typedef HRESULT (CALLBACK* DLLGETVERSIONPROC)(DLLVERSIONINFO *);
33 
34 #endif
35 
36 #ifdef OVL0
37 #define SHARED_DCL
38 #else
39 #define SHARED_DCL extern
40 #endif
41 
42 /* Minimal common control library version
43 Version     _WIN_32IE   Platform/IE
44 =======     =========   ===========
45 4.00        0x0200      Microsoft(r) Windows 95/Windows NT 4.0
46 4.70        0x0300      Microsoft(r) Internet Explorer 3.x
47 4.71        0x0400      Microsoft(r) Internet Explorer 4.0
48 4.72        0x0401      Microsoft(r) Internet Explorer 4.01
49 ...and probably going on infinitely...
50 */
51 #define MIN_COMCTLMAJOR 4
52 #define MIN_COMCTLMINOR 71
53 #define INSTALL_NOTES "http://www.nethack.org/v340/ports/download-win.html#cc"
54 /*#define COMCTL_URL "http://www.microsoft.com/msdownload/ieplatform/ie/comctrlx86.asp"*/
55 
56 extern void FDECL(nethack_exit,(int));
57 static TCHAR* _get_cmd_arg(TCHAR* pCmdLine);
58 static HRESULT GetComCtlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor);
59 
60 
61 // Global Variables:
62 NHWinApp _nethack_app;
63 
64 #ifdef __BORLANDC__
65 #define _stricmp(s1,s2)     stricmp(s1,s2)
66 #define _strdup(s1)         strdup(s1)
67 #endif
68 
69 // Foward declarations of functions included in this code module:
70 extern void FDECL(pcmain, (int,char **));
71 static void __cdecl mswin_moveloop(void *);
72 
73 #define MAX_CMDLINE_PARAM 255
74 
WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)75 int APIENTRY WinMain(HINSTANCE hInstance,
76                      HINSTANCE hPrevInstance,
77                      LPSTR     lpCmdLine,
78                      int       nCmdShow)
79 {
80 	INITCOMMONCONTROLSEX InitCtrls;
81 	int argc;
82 	char* argv[MAX_CMDLINE_PARAM];
83 	size_t len;
84 	TCHAR *p;
85 	TCHAR wbuf[BUFSZ];
86 	char buf[BUFSZ];
87     DWORD major, minor;
88 
89 
90 	/* ensure that we don't access violate on a panic() */
91 	windowprocs.win_raw_print = mswin_raw_print;
92 	windowprocs.win_raw_print_bold = mswin_raw_print_bold;
93 
94 	/* init applicatio structure */
95 	_nethack_app.hApp = hInstance;
96 	_nethack_app.hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_NETHACKW);
97 	_nethack_app.hMainWnd = NULL;
98 	_nethack_app.hPopupWnd = NULL;
99 	_nethack_app.bmpTiles = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_TILES));
100 	if( _nethack_app.bmpTiles==NULL ) panic("cannot load tiles bitmap");
101 	_nethack_app.bmpPetMark = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_PETMARK));
102 	if( _nethack_app.bmpPetMark==NULL ) panic("cannot load pet mark bitmap");
103 	_nethack_app.bmpRip = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_RIP));
104 	if ( _nethack_app.bmpRip == NULL ) panic("cannot load rip bitmap");
105 	_nethack_app.bmpSplash = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_SPLASH));
106 	if ( _nethack_app.bmpSplash == NULL ) panic("cannot load splash bitmap");
107 	_nethack_app.bmpMapTiles = _nethack_app.bmpTiles;
108 	_nethack_app.mapTile_X = TILE_X;
109 	_nethack_app.mapTile_Y = TILE_Y;
110 	_nethack_app.mapTilesPerLine = TILES_PER_LINE;
111 
112 	_nethack_app.bNoHScroll = FALSE;
113 	_nethack_app.bNoVScroll = FALSE;
114 	_nethack_app.saved_text = strdup("");
115 
116     // init controls
117     if (FAILED(GetComCtlVersion(&major, &minor)))
118     {
119         char buf[TBUFSZ];
120         Sprintf(buf, "Cannot load common control library.\n%s\n%s",
121               "For further information, refer to the installation notes at",
122 		INSTALL_NOTES);
123         panic(buf);
124     }
125     if (major < MIN_COMCTLMAJOR
126         || (major == MIN_COMCTLMAJOR && minor < MIN_COMCTLMINOR))
127     {
128         char buf[TBUFSZ];
129         Sprintf(buf, "Common control library is outdated.\n%s %d.%d\n%s\n%s",
130               "NetHack requires at least version ",
131 	      MIN_COMCTLMAJOR, MIN_COMCTLMINOR,
132 	      "For further information, refer to the installation notes at",
133 		INSTALL_NOTES);
134         panic(buf);
135     }
136 	ZeroMemory(&InitCtrls, sizeof(InitCtrls));
137 	InitCtrls.dwSize = sizeof(InitCtrls);
138 	InitCtrls.dwICC = ICC_LISTVIEW_CLASSES;
139 	InitCommonControlsEx(&InitCtrls);
140 
141 	/* get command line parameters */
142 	p = _get_cmd_arg(GetCommandLine());
143 	p = _get_cmd_arg(NULL); /* skip first paramter - command name */
144 	for( argc = 1; p && argc<MAX_CMDLINE_PARAM; argc++ ) {
145 		len = _tcslen(p);
146 		if( len>0 ) {
147 			argv[argc] = _strdup( NH_W2A(p, buf, BUFSZ) );
148 		} else {
149 			argv[argc] = "";
150 		}
151 		p = _get_cmd_arg(NULL);
152 	}
153 	GetModuleFileName(NULL, wbuf, BUFSZ);
154 	argv[0] = _strdup(NH_W2A(wbuf, buf, BUFSZ));
155 
156     if (argc == 2) {
157 	    TCHAR *savefile = strdup(argv[1]);
158 	    TCHAR *plname;
159         for (p = savefile; *p && *p != '-'; p++)
160             ;
161         if (*p) {
162             /* we found a '-' */
163             plname = p + 1;
164             for (p = plname; *p && *p != '.'; p++)
165                 ;
166             if (*p) {
167                 if (strcmp(p + 1, "NetHack-saved-game") == 0) {
168                     *p = '\0';
169                     argv[1] = "-u";
170                     argv[2] = _strdup(plname);
171                     argc = 3;
172                 }
173             }
174         }
175         free(savefile);
176     }
177 	pcmain(argc,argv);
178 
179 	moveloop();
180 
181 	return 0;
182 }
183 
184 
GetNHApp()185 PNHWinApp GetNHApp()
186 {
187 	return &_nethack_app;
188 }
189 
_get_cmd_arg(TCHAR * pCmdLine)190 TCHAR* _get_cmd_arg(TCHAR* pCmdLine)
191 {
192         static TCHAR* pArgs = NULL;
193         TCHAR  *pRetArg;
194         BOOL   bQuoted;
195 
196         if( !pCmdLine && !pArgs ) return NULL;
197         if( !pArgs ) pArgs = pCmdLine;
198 
199         /* skip whitespace */
200         for(pRetArg = pArgs; *pRetArg && _istspace(*pRetArg); pRetArg = CharNext(pRetArg));
201 		if( !*pRetArg ) {
202 			pArgs = NULL;
203 			return NULL;
204 		}
205 
206         /* check for quote */
207         if( *pRetArg==TEXT('"') ) {
208                 bQuoted = TRUE;
209                 pRetArg = CharNext(pRetArg);
210 				pArgs = _tcschr(pRetArg, TEXT('"'));
211 	    } else {
212 			/* skip to whitespace */
213 			for(pArgs = pRetArg; *pArgs && !_istspace(*pArgs); pArgs = CharNext(pArgs));
214 		}
215 
216 		if( pArgs && *pArgs ) {
217 			TCHAR* p;
218 			p = pArgs;
219 			pArgs = CharNext(pArgs);
220 			*p = (TCHAR)0;
221 		} else {
222 			pArgs = NULL;
223 		}
224 
225 		return pRetArg;
226 }
227 
228 /* Get the version of the Common Control library on this machine.
229    Copied from the Microsoft SDK
230  */
GetComCtlVersion(LPDWORD pdwMajor,LPDWORD pdwMinor)231 HRESULT GetComCtlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor)
232 {
233 	HINSTANCE   hComCtl;
234 	HRESULT           hr = S_OK;
235 	DLLGETVERSIONPROC pDllGetVersion;
236 
237 	if(IsBadWritePtr(pdwMajor, sizeof(DWORD)) ||
238 	   IsBadWritePtr(pdwMinor, sizeof(DWORD)))
239 		return E_INVALIDARG;
240 	//load the DLL
241 	hComCtl = LoadLibrary(TEXT("comctl32.dll"));
242 	if (!hComCtl) return E_FAIL;
243 
244 	/*
245 	You must get this function explicitly because earlier versions of the DLL
246 	don't implement this function. That makes the lack of implementation of the
247 	function a version marker in itself.
248 	*/
249 	pDllGetVersion = (DLLGETVERSIONPROC)GetProcAddress(hComCtl, TEXT("DllGetVersion"));
250 	if(pDllGetVersion) {
251 		DLLVERSIONINFO    dvi;
252 		ZeroMemory(&dvi, sizeof(dvi));
253 		dvi.cbSize = sizeof(dvi);
254 		hr = (*pDllGetVersion)(&dvi);
255 		if(SUCCEEDED(hr)) {
256 			*pdwMajor = dvi.dwMajorVersion;
257 			*pdwMinor = dvi.dwMinorVersion;
258                 } else {
259 			hr = E_FAIL;
260                 }
261         } else {
262 		/*
263 		If GetProcAddress failed, then the DLL is a version previous to the one
264 		shipped with IE 3.x.
265 		*/
266 		*pdwMajor = 4;
267 		*pdwMinor = 0;
268 	}
269 	FreeLibrary(hComCtl);
270 	return hr;
271 }
272 
273 
274