1 /*	SCCS Id: @(#)winnt.c	 3.4	 $Date: 2003/10/26 15:58:22 $		  */
2 /* Copyright (c) NetHack PC Development Team 1993, 1994 */
3 /* NetHack may be freely redistributed.  See license for details. */
4 
5 /*
6  *  WIN32 system functions.
7  *
8  *  Initial Creation: Michael Allison - January 31/93
9  *
10  */
11 
12 #define NEED_VARARGS
13 #include "hack.h"
14 #include <dos.h>
15 #ifndef __BORLANDC__
16 #include <direct.h>
17 #endif
18 #include <ctype.h>
19 #include "win32api.h"
20 #ifdef WIN32CON
21 #include "wintty.h"
22 #endif
23 #ifdef WIN32
24 
25 
26 /*
27  * The following WIN32 API routines are used in this file.
28  *
29  * GetDiskFreeSpace
30  * GetVolumeInformation
31  * GetUserName
32  * FindFirstFile
33  * FindNextFile
34  * FindClose
35  *
36  */
37 
38 
39 /* globals required within here */
40 HANDLE ffhandle = (HANDLE)0;
41 WIN32_FIND_DATA ffd;
42 
43 /* The function pointer nt_kbhit contains a kbhit() equivalent
44  * which varies depending on which window port is active.
45  * For the tty port it is tty_kbhit() [from nttty.c]
46  * For the win32 port it is win32_kbhit() [from winmain.c]
47  * It is initialized to point to def_kbhit [in here] for safety.
48  */
49 
50 int def_kbhit(void);
51 int (*nt_kbhit)() = def_kbhit;
52 
53 char
switchar()54 switchar()
55 {
56  /* Could not locate a WIN32 API call for this- MJA */
57 	return '-';
58 }
59 
60 long
freediskspace(path)61 freediskspace(path)
62 char *path;
63 {
64 	char tmppath[4];
65 	DWORD SectorsPerCluster = 0;
66 	DWORD BytesPerSector = 0;
67 	DWORD FreeClusters = 0;
68 	DWORD TotalClusters = 0;
69 
70 	tmppath[0] = *path;
71 	tmppath[1] = ':';
72 	tmppath[2] = '\\';
73 	tmppath[3] = '\0';
74 	GetDiskFreeSpace(tmppath, &SectorsPerCluster,
75 			&BytesPerSector,
76 			&FreeClusters,
77 			&TotalClusters);
78 	return (long)(SectorsPerCluster * BytesPerSector *
79 			FreeClusters);
80 }
81 
82 /*
83  * Functions to get filenames using wildcards
84  */
85 int
findfirst(path)86 findfirst(path)
87 char *path;
88 {
89 	if (ffhandle){
90 		 FindClose(ffhandle);
91 		 ffhandle = (HANDLE)0;
92 	}
93 	ffhandle = FindFirstFile(path,&ffd);
94 	return
95 	  (ffhandle == INVALID_HANDLE_VALUE) ? 0 : 1;
96 }
97 
98 int
findnext()99 findnext()
100 {
101 	return FindNextFile(ffhandle,&ffd) ? 1 : 0;
102 }
103 
104 char *
foundfile_buffer()105 foundfile_buffer()
106 {
107 	return &ffd.cFileName[0];
108 }
109 
110 long
filesize(file)111 filesize(file)
112 char *file;
113 {
114 	if (findfirst(file)) {
115 		return ((long)ffd.nFileSizeLow);
116 	} else
117 		return -1L;
118 }
119 
120 /*
121  * Chdrive() changes the default drive.
122  */
123 void
chdrive(str)124 chdrive(str)
125 char *str;
126 {
127 	char *ptr;
128 	char drive;
129 	if ((ptr = index(str, ':')) != (char *)0)
130 	{
131 		drive = toupper(*(ptr - 1));
132 		_chdrive((drive - 'A') + 1);
133 	}
134 }
135 
136 static int
max_filename()137 max_filename()
138 {
139 	DWORD maxflen;
140 	int status=0;
141 
142 	status = GetVolumeInformation((LPTSTR)0,(LPTSTR)0, 0
143 			,(LPDWORD)0,&maxflen,(LPDWORD)0,(LPTSTR)0,0);
144 	if (status) return maxflen;
145 	else return 0;
146 }
147 
148 int
def_kbhit()149 def_kbhit()
150 {
151 	return 0;
152 }
153 
154 /*
155  * Strip out troublesome file system characters.
156  */
157 
158 void
nt_regularize(s)159 nt_regularize(s)	/* normalize file name */
160 register char *s;
161 {
162 	register unsigned char *lp;
163 
164 	for (lp = s; *lp; lp++)
165 	    if ( *lp == '?' || *lp == '"' || *lp == '\\' ||
166 		 *lp == '/' || *lp == '>' || *lp == '<'  ||
167 		 *lp == '*' || *lp == '|' || *lp == ':'  || (*lp > 127))
168 			*lp = '_';
169 }
170 
171 /*
172  * This is used in nhlan.c to implement some of the LAN_FEATURES.
173  */
get_username(lan_username_size)174 char *get_username(lan_username_size)
175 int *lan_username_size;
176 {
177 	static TCHAR username_buffer[BUFSZ];
178 	unsigned int status;
179 	DWORD i = BUFSZ - 1;
180 
181 	/* i gets updated with actual size */
182 	status = GetUserName(username_buffer, &i);
183 	if (status) username_buffer[i] = '\0';
184 	else Strcpy(username_buffer, "NetHack");
185 	if (lan_username_size) *lan_username_size = strlen(username_buffer);
186 	return username_buffer;
187 }
188 
189 # if 0
getxxx()190 char *getxxx()
191 {
192 char     szFullPath[MAX_PATH] = "";
193 HMODULE  hInst = NULL;  	/* NULL gets the filename of this module */
194 
195 GetModuleFileName(hInst, szFullPath, sizeof(szFullPath));
196 return &szFullPath[0];
197 }
198 # endif
199 
200 #ifndef WIN32CON
201 /* fatal error */
202 /*VARARGS1*/
203 void
204 error VA_DECL(const char *,s)
205 	char buf[BUFSZ];
206 	VA_START(s);
207 	VA_INIT(s, const char *);
208 	/* error() may get called before tty is initialized */
209 	if (iflags.window_inited) end_screen();
210 	if (!strncmpi(windowprocs.name, "tty", 3)) {
211 		buf[0] = '\n';
212 		(void) vsprintf(&buf[1], s, VA_ARGS);
213 		Strcat(buf, "\n");
214 		msmsg(buf);
215 	} else {
216 		(void) vsprintf(buf, s, VA_ARGS);
217 		Strcat(buf, "\n");
218 		raw_printf(buf);
219 	}
220 	VA_END();
221 	exit(EXIT_FAILURE);
222 }
223 #endif
224 
225 void Delay(int ms)
226 {
227 	(void)Sleep(ms);
228 }
229 
230 #ifdef WIN32CON
231 extern void NDECL(backsp);
232 #endif
233 
234 void win32_abort()
235 {
236 #ifdef WIZARD
237    	if (wizard) {
238 # ifdef WIN32CON
239 	    int c, ci, ct;
240 
241    	    if (!iflags.window_inited)
242 		c = 'n';
243 		ct = 0;
244 		msmsg("Execute debug breakpoint wizard?");
245 		while ((ci=nhgetch()) != '\n') {
246 		    if (ct > 0) {
247 			backsp();       /* \b is visible on NT */
248 			(void) putchar(' ');
249 			backsp();
250 			ct = 0;
251 			c = 'n';
252 		    }
253 		    if (ci == 'y' || ci == 'n' || ci == 'Y' || ci == 'N') {
254 		    	ct = 1;
255 		        c = ci;
256 		        msmsg("%c",c);
257 		    }
258 		}
259 		if (c == 'y')
260 			DebugBreak();
261 # endif
262 	}
263 #endif
264 	abort();
265 }
266 
267 static char interjection_buf[INTERJECTION_TYPES][1024];
268 static int interjection[INTERJECTION_TYPES];
269 
270 void
271 interject_assistance(num, interjection_type, ptr1, ptr2)
272 int num;
273 int interjection_type;
274 genericptr_t ptr1;
275 genericptr_t ptr2;
276 {
277 	switch(num) {
278 	    case 1: {
279 		char *panicmsg = (char *)ptr1;
280 		char *datadir =  (char *)ptr2;
281 		char *tempdir = nh_getenv("TEMP");
282 		interjection_type = INTERJECT_PANIC;
283 		interjection[INTERJECT_PANIC] = 1;
284 		/*
285 		 * ptr1 = the panic message about to be delivered.
286 		 * ptr2 = the directory prefix of the dungeon file
287 		 *        that failed to open.
288 		 * Check to see if datadir matches tempdir or a
289 		 * common windows temp location. If it does, inform
290 		 * the user that they are probably trying to run the
291 		 * game from within their unzip utility, so the required
292 		 * files really don't exist at the location. Instruct
293 		 * them to unpack them first.
294 		 */
295 		if (panicmsg && datadir) {
296 		    if (!strncmpi(datadir, "C:\\WINDOWS\\TEMP", 15) ||
297 			    strstri(datadir, "TEMP")   ||
298 			    (tempdir && strstri(datadir, tempdir))) {
299 			(void)strncpy(interjection_buf[INTERJECT_PANIC],
300 			"\nOne common cause of this error is attempting to execute\n"
301 			"the game by double-clicking on it while it is displayed\n"
302 			"inside an unzip utility.\n\n"
303 			"You have to unzip the contents of the zip file into a\n"
304 			"folder on your system, and then run \"NetHack.exe\" or \n"
305 			"\"NetHackW.exe\" from there.\n\n"
306 			"If that is not the situation, you are encouraged to\n"
307 			"report the error as shown above.\n\n", 1023);
308 		    }
309 		}
310 	    }
311 	    break;
312 	}
313 }
314 
315 void
316 interject(interjection_type)
317 int interjection_type;
318 {
319 	if (interjection_type >= 0 && interjection_type < INTERJECTION_TYPES)
320 		msmsg(interjection_buf[interjection_type]);
321 }
322 #endif /* WIN32 */
323 
324 /*winnt.c*/
325