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