source: trunk/src/kernel32/oslibdos.cpp@ 1924

Last change on this file since 1924 was 1924, checked in by sandervl, 26 years ago

added GetProcessTimes + several fixes

File size: 19.0 KB
Line 
1/* $Id: oslibdos.cpp,v 1.12 1999-12-01 18:40:48 sandervl Exp $ */
2
3/*
4 * Wrappers for OS/2 Dos* API
5 *
6 * Copyright 1998 Sander van Leeuwen (sandervl@xs4all.nl)
7 *
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12#define INCL_BASE
13#define INCL_DOSEXCEPTIONS
14#define INCL_DOSMEMMGR
15#define INCL_DOSPROCESS
16#define INCL_DOSERRORS
17#include <os2wrap.h> //Odin32 OS/2 api wrappers
18#include <stdlib.h>
19#include <stdio.h>
20#include <string.h>
21#include <win32type.h>
22#include <misc.h>
23#include "initterm.h"
24#include "oslibdos.h"
25#include "dosqss.h"
26
27APIRET APIENTRY DosAliasMem(PVOID pb, ULONG cb, PPVOID ppbAlias, ULONG fl);
28
29//******************************************************************************
30//TODO: Assumes entire memory range has the same protection flags!
31//TODO: Check if this works for code aliases...
32//******************************************************************************
33DWORD OSLibDosAliasMem(LPVOID pb, ULONG cb, LPVOID *ppbAlias, ULONG fl)
34{
35 DWORD rc;
36 DWORD attr;
37 DWORD size = cb;
38
39 cb = (cb-1) & ~0xfff;
40 cb+= PAGE_SIZE;
41
42 rc = DosQueryMem(pb, &size, &attr);
43 if(rc) {
44 dprintf(("OSLibDosAliasMem: DosQueryMem %x %x return %d", pb, size, rc));
45 return rc;
46 }
47 size = (size-1) & ~0xfff;
48 size+= PAGE_SIZE;
49 if(size != cb) {
50 dprintf(("ERROR: OSLibDosAliasMem: size != cb (%x!=%x)!!!!!!!!", size, cb));
51 //ignore this and continue return 5;
52 attr = fl; //just use original protection flags (NOT CORRECT)
53 }
54 attr &= (PAG_READ|PAG_WRITE|PAG_EXECUTE|PAG_GUARD|PAG_DEFAULT);
55 if(attr != fl) {
56 rc = DosSetMem(pb, size, fl);
57 if(rc) {
58 dprintf(("OSLibDosAliasMem: DosSetMem %x %x return %d", pb, size, rc));
59 attr = fl;
60 //just continue for now
61 //return rc;
62 }
63 }
64 rc = DosAliasMem(pb, cb, ppbAlias, 2);
65 if(rc) {
66 dprintf(("OSLibDosAliasMem: DosAliasMem %x %x return %d", pb, cb, rc));
67 return rc;
68 }
69 if(attr != fl) {
70 rc = DosSetMem(pb, size, attr);
71 if(rc) {
72 dprintf(("OSLibDosAliasMem: DosSetMem (2) %x %x return %d", pb, size, rc));
73 return rc;
74 }
75 }
76 return 0;
77}
78//******************************************************************************
79//NT returns addresses aligned at 64k, so we do too.
80//******************************************************************************
81DWORD OSLibDosAllocMem(LPVOID *lplpMemAddr, DWORD size, DWORD flags)
82{
83 LPVOID memaddr;
84 DWORD offset;
85 APIRET rc;
86
87 rc = DosAllocMem(&memaddr, size, PAG_READ | flAllocMem);
88 if(rc) {
89 return rc;
90 }
91 DosEnterCritSec();
92 DosFreeMem(memaddr);
93 offset = (DWORD)memaddr & 0xFFFF;
94 if(offset) {
95 DosAllocMem(&memaddr, 64*1024 - offset, PAG_READ | flAllocMem);
96 }
97 rc = DosAllocMem(lplpMemAddr, size, flags | flAllocMem);
98 DosExitCritSec();
99 if((DWORD)*lplpMemAddr & 0xFFFF) {//still not at 64k boundary?
100 DosFreeMem(*lplpMemAddr);
101 rc = OSLibDosAllocMem(lplpMemAddr, size, flags);
102 }
103 if(offset) {
104 DosFreeMem(memaddr);
105 }
106
107 return rc;
108}
109//******************************************************************************
110//******************************************************************************
111DWORD OSLibDosFreeMem(LPVOID lpMemAddr)
112{
113 return DosFreeMem(lpMemAddr);
114}
115//******************************************************************************
116//NOTE: If name == NULL, allocated gettable unnamed shared memory
117//******************************************************************************
118DWORD OSLibDosAllocSharedMem(LPVOID *lplpMemAddr, DWORD size, DWORD flags, LPSTR name)
119{
120 APIRET rc;
121 char *sharedmemname = NULL;
122
123 if(name) {
124 sharedmemname = (char *)malloc(strlen(name) + 16);
125 strcpy(sharedmemname, "\\SHAREMEM\\");
126 strcat(sharedmemname, name);
127 }
128 else flags |= OBJ_GETTABLE;
129
130 rc = DosAllocSharedMem(lplpMemAddr, sharedmemname, size, flags);
131 if(name) {
132 free(sharedmemname);
133 }
134 return rc;
135}
136//******************************************************************************
137//NOTE: If name == NULL, assume gettable unnamed shared memory
138//******************************************************************************
139DWORD OSLibDosGetNamedSharedMem(LPVOID *lplpMemAddr, LPSTR name)
140{
141 APIRET rc;
142 char *sharedmemname = NULL;
143
144 if(name) {
145 sharedmemname = (char *)malloc(strlen(name) + 16);
146 strcpy(sharedmemname, "\\SHAREMEM\\");
147 strcat(sharedmemname, name);
148 rc = DosGetNamedSharedMem(lplpMemAddr, sharedmemname, PAG_READ|PAG_WRITE);
149 if(name) {
150 free(sharedmemname);
151 }
152 }
153 else rc = DosGetSharedMem((LPVOID)*(DWORD *)lplpMemAddr, PAG_READ|PAG_WRITE);
154
155 return rc;
156}
157//******************************************************************************
158//******************************************************************************
159DWORD OSLibDosQueryMem(LPVOID lpMemAddr, DWORD *lpRangeSize, DWORD *lpAttr)
160{
161 return DosQueryMem(lpMemAddr, lpRangeSize, lpAttr);
162}
163//******************************************************************************
164//******************************************************************************
165DWORD OSLibDosSetMem(LPVOID lpMemAddr, DWORD size, DWORD flags)
166{
167 APIRET rc;
168
169 rc = DosSetMem(lpMemAddr, size, flags);
170 switch(rc) {
171 case ERROR_INVALID_ADDRESS:
172 return OSLIB_ERROR_INVALID_ADDRESS;
173 case ERROR_ACCESS_DENIED:
174 return OSLIB_ERROR_ACCESS_DENIED;
175 default:
176 return rc;
177 }
178}
179//******************************************************************************
180//******************************************************************************
181DWORD OSLibDosOpen(char *lpszFileName, DWORD flags)
182{
183 APIRET rc;
184 HFILE hFile;
185 ULONG ulAction;
186 DWORD os2flags = OPEN_FLAGS_NOINHERIT;
187
188
189 if(flags & OSLIB_ACCESS_READONLY)
190 os2flags |= OPEN_ACCESS_READONLY;
191 else
192 if(flags & OSLIB_ACCESS_READWRITE)
193 os2flags |= OPEN_ACCESS_READWRITE;
194
195 if(flags & OSLIB_ACCESS_SHAREDENYNONE)
196 os2flags |= OPEN_SHARE_DENYNONE;
197 else
198 if(flags & OSLIB_ACCESS_SHAREDENYREAD)
199 os2flags |= OPEN_SHARE_DENYREAD;
200 else
201 if(flags & OSLIB_ACCESS_SHAREDENYWRITE)
202 os2flags |= OPEN_SHARE_DENYWRITE;
203
204tryopen:
205 rc = DosOpen(lpszFileName, /* File path name */
206 &hFile, /* File handle */
207 &ulAction, /* Action taken */
208 0L, /* File primary allocation */
209 0L, /* File attribute */
210 OPEN_ACTION_FAIL_IF_NEW |
211 OPEN_ACTION_OPEN_IF_EXISTS, /* Open function type */
212 os2flags,
213 0L); /* No extended attribute */
214
215 if(rc) {
216 if(rc == ERROR_TOO_MANY_OPEN_FILES) {
217 ULONG CurMaxFH;
218 LONG ReqCount = 32;
219
220 rc = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
221 if(rc) {
222 dprintf(("DosSetRelMaxFH returned %d", rc));
223 return 0;
224 }
225 dprintf(("DosOpen failed -> increased nr open files to %d", CurMaxFH));
226 goto tryopen;
227 }
228 return 0;
229 }
230 else return hFile;
231}
232//******************************************************************************
233//******************************************************************************
234DWORD OSLibDosClose(DWORD hFile)
235{
236 return DosClose(hFile);
237}
238//******************************************************************************
239//******************************************************************************
240DWORD OSLibDosRead(DWORD hFile, LPVOID lpBuffer, DWORD size, DWORD *nrBytesRead)
241{
242 return DosRead(hFile, lpBuffer, size, nrBytesRead);
243}
244//******************************************************************************
245//******************************************************************************
246DWORD OSLibDosWrite(DWORD hFile, LPVOID lpBuffer, DWORD size, DWORD *nrBytesWritten)
247{
248 return DosWrite(hFile, lpBuffer, size, nrBytesWritten);
249}
250//******************************************************************************
251//******************************************************************************
252DWORD OSLibDosSetFilePtr(DWORD hFile, DWORD offset, DWORD method)
253{
254 DWORD os2method;
255 DWORD newoffset;
256 APIRET rc;
257
258 switch(method) {
259 case OSLIB_SETPTR_FILE_CURRENT:
260 os2method = FILE_CURRENT;
261 break;
262 case OSLIB_SETPTR_FILE_BEGIN:
263 os2method = FILE_BEGIN ;
264 break;
265 case OSLIB_SETPTR_FILE_END:
266 os2method = FILE_END;
267 break;
268 default:
269 return OSLIB_ERROR_INVALID_PARAMETER;
270 }
271 rc = DosSetFilePtr(hFile, offset, os2method, &newoffset);
272 if(rc) {
273 return -1;
274 }
275 else return newoffset;
276}
277//******************************************************************************
278//******************************************************************************
279//@@@PH Note: this routine is nothing but a QUICK'N'DIRTY HACK!
280//@@@PH this function should be implemented accordingly to NTDLL's
281// RtlSecondsSince1980ToTime
282// RtlTimeToSecondsSince1980
283static void iFDATEFTIME2FILETIME(FDATE fdOS2, FTIME ftOS2, LPFILETIME pftWin32)
284{
285 float f;
286 #define facSECOND 2 // as encoded in OS/2
287 #define facMINUTE 60
288 #define facHOUR 3600
289 #define facDAY 86400
290 #define facMONTH facDAY * 30 // cough, cough :)
291 #define facYEAR facDAY * 365
292
293 /* pftWin32 is 100ns based from 01.01.1601 00:00:00 */
294 f = (fdOS2.year + 379) * facYEAR // 1980 - 1601
295 + (fdOS2.month - 0 ) * facMONTH
296 + (fdOS2.day - 1 ) * facDAY
297 + (ftOS2.hours ) * facHOUR
298 + (ftOS2.minutes ) * facMINUTE
299 + (ftOS2.twosecs ) * facSECOND;
300
301 f *= 10000; // convert to 100ns base
302 pftWin32->dwHighDateTime = (f / (float)(0xffffffff) );
303 pftWin32->dwLowDateTime = (f - (float)((float)pftWin32->dwHighDateTime *
304 (float)0xffffffff) );
305}
306
307BOOL OSLibDosGetFileAttributesEx(PSZ pszName,
308 ULONG ulDummy,
309 PVOID pBuffer)
310{
311 APIRET rc; /* API return code */
312 FILESTATUS3 fs3; /* file information structure */
313 LPWIN32_FILE_ATTRIBUTE_DATA lpFad = (LPWIN32_FILE_ATTRIBUTE_DATA) pBuffer;
314
315 // Note: we only handle standard "GetFileExInfoStandard" requests
316 rc = DosQueryPathInfo(pszName, /* query the file information */
317 FIL_STANDARD,
318 &fs3,
319 sizeof(fs3));
320 if (rc != NO_ERROR) /* check for errors */
321 return FALSE; /* raise error condition */
322
323 // convert structure
324 lpFad->dwFileAttributes = fs3.attrFile; // directly interchangeable
325 iFDATEFTIME2FILETIME(fs3.fdateCreation, fs3.ftimeCreation, &lpFad->ftCreationTime);
326 iFDATEFTIME2FILETIME(fs3.fdateLastAccess, fs3.ftimeLastAccess, &lpFad->ftLastAccessTime);
327 iFDATEFTIME2FILETIME(fs3.fdateLastWrite, fs3.ftimeLastWrite, &lpFad->ftLastWriteTime);
328
329 /* @@@PH we might add Aurora support ...
330 lpFad->nFileSizeHigh = info.nFileSizeHigh;
331 */
332 lpFad->nFileSizeHigh = 0;
333 lpFad->nFileSizeLow = fs3.cbFile;
334
335 return TRUE;
336}
337//******************************************************************************
338//******************************************************************************
339DWORD OSLibDosSearchPath(DWORD cmd, char *path, char *name, char *full_name,
340 DWORD length_fullname)
341{
342 switch(cmd) {
343 case OSLIB_SEARCHDIR:
344 if(DosSearchPath(SEARCH_IGNORENETERRS, path,
345 name, full_name, length_fullname) != 0) {
346 return 0;
347 }
348 return strlen(full_name);
349
350
351 case OSLIB_SEARCHCURDIR:
352 if(DosSearchPath(SEARCH_IGNORENETERRS | SEARCH_CUR_DIRECTORY, path,
353 name, full_name, length_fullname) != 0) {
354 return 0;
355 }
356 return strlen(full_name);
357
358 case OSLIB_SEARCHFILE:
359 {
360 FILESTATUS3 fileinfo;
361
362 if(DosQueryPathInfo(name, FIL_STANDARD, &fileinfo, sizeof(fileinfo)) != 0) {
363 return 0;
364 }
365 strncpy(full_name, name, length_fullname);
366 return strlen(full_name);
367 }
368
369 case OSLIB_SEARCHENV:
370 {
371 char *env = getenv(path);
372 if(env == NULL)
373 return 0;
374
375 while(*env != '=') env++;
376 env++;
377 while(*env == ' ') env++;
378 if(DosSearchPath(SEARCH_IGNORENETERRS | SEARCH_ENVIRONMENT, env,
379 name, full_name, length_fullname) != 0) {
380 return 0;
381 }
382 return strlen(full_name);
383 }
384 }
385 return 0;
386}
387//******************************************************************************
388//******************************************************************************
389DWORD OSLibDosCreate(CHAR *lpFileName,
390 DWORD dwAccess,
391 DWORD dwShare,
392 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
393 DWORD dwCreation,
394 DWORD dwFlags,
395 HANDLE hTemplate,
396 DWORD *dwFile)
397{
398 APIRET rc;
399 HFILE hFile;
400 ULONG ulAction=0;
401 DWORD os2Attrib=0;
402 DWORD os2Flags = 0; //OPEN_FLAGS_NOINHERIT;
403 DWORD os2Open=0;
404
405#define GENERIC_READ 0x80000000
406#define GENERIC_WRITE 0x40000000
407 if(dwAccess == (GENERIC_READ | GENERIC_WRITE))
408 os2Flags |= OPEN_ACCESS_READWRITE;
409 else if(dwAccess & GENERIC_WRITE)
410 os2Flags |= OPEN_ACCESS_WRITEONLY;
411 else if(dwAccess & GENERIC_READ)
412 os2Flags |= OPEN_ACCESS_READONLY;
413
414#define FILE_SHARE_READ 0x00000001L
415#define FILE_SHARE_WRITE 0x00000002L
416 if(dwShare == 0)
417 os2Flags |= OPEN_SHARE_DENYREADWRITE;
418 else if(dwShare == (FILE_SHARE_READ | FILE_SHARE_WRITE))
419 os2Flags |= OPEN_SHARE_DENYNONE;
420 else if(dwShare & FILE_SHARE_READ)
421 os2Flags |= OPEN_SHARE_DENYWRITE;
422 else if(dwShare & FILE_SHARE_WRITE)
423 os2Flags |= OPEN_SHARE_DENYREAD;
424
425#define CREATE_NEW 1
426#define CREATE_ALWAYS 2
427#define OPEN_EXISTING 3
428#define OPEN_ALWAYS 4
429#define TRUNCATE_EXISTING 5
430 if(dwCreation == CREATE_NEW)
431 os2Open = OPEN_ACTION_FAIL_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW;
432 else if(dwCreation == CREATE_ALWAYS)
433 os2Open = OPEN_ACTION_REPLACE_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW;
434 else if(dwCreation == OPEN_EXISTING)
435 os2Open = OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW;
436 else if(dwCreation == OPEN_ALWAYS)
437 os2Open = OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_CREATE_IF_NEW;
438 else if(dwCreation == TRUNCATE_EXISTING)
439 os2Open = OPEN_ACTION_REPLACE_IF_EXISTS;// |OPEN_ACTION_FAIL_IF_NEW;
440
441#define FILE_ATTRIBUTE_READONLY 0x00000001L
442#define FILE_ATTRIBUTE_HIDDEN 0x00000002L
443#define FILE_ATTRIBUTE_SYSTEM 0x00000004L
444#define FILE_ATTRIBUTE_DIRECTORY 0x00000010L
445#define FILE_ATTRIBUTE_ARCHIVE 0x00000020L
446#define FILE_ATTRIBUTE_NORMAL 0x00000080L
447#define FILE_ATTRIBUTE_TEMPORARY 0x00000100L
448 if(dwFlags & FILE_ATTRIBUTE_READONLY)
449 os2Attrib |= FILE_READONLY;
450 if(dwFlags & FILE_ATTRIBUTE_HIDDEN)
451 os2Attrib |= FILE_HIDDEN;
452 if(dwFlags & FILE_ATTRIBUTE_SYSTEM)
453 os2Attrib |= FILE_SYSTEM;
454 if(dwFlags & FILE_ATTRIBUTE_DIRECTORY)
455 os2Attrib |= FILE_DIRECTORY;
456 if(dwFlags & FILE_ATTRIBUTE_ARCHIVE)
457 os2Attrib |= FILE_ARCHIVED;
458 if(dwFlags & FILE_ATTRIBUTE_NORMAL)
459 os2Attrib |= FILE_NORMAL;
460
461#define FILE_FLAG_WRITE_THROUGH 0x80000000UL
462#define FILE_FLAG_OVERLAPPED 0x40000000L
463#define FILE_FLAG_NO_BUFFERING 0x20000000L
464#define FILE_FLAG_RANDOM_ACCESS 0x10000000L
465#define FILE_FLAG_SEQUENTIAL_SCAN 0x08000000L
466#define FILE_FLAG_DELETE_ON_CLOSE 0x04000000L
467#define FILE_FLAG_BACKUP_SEMANTICS 0x02000000L
468#define FILE_FLAG_POSIX_SEMANTICS 0x01000000L
469 if(dwFlags & FILE_FLAG_WRITE_THROUGH)
470 os2Flags |= OPEN_FLAGS_WRITE_THROUGH;
471 if(dwFlags & FILE_FLAG_NO_BUFFERING)
472 os2Flags |= OPEN_FLAGS_NO_CACHE;
473 if(dwFlags & FILE_FLAG_RANDOM_ACCESS)
474 os2Flags |= OPEN_FLAGS_RANDOM;
475 if(dwFlags & FILE_FLAG_SEQUENTIAL_SCAN)
476 os2Flags |= OPEN_FLAGS_SEQUENTIAL;
477
478 // TODO:
479 // if(dwFlags & FILE_FLAG_OVERLAPPED)
480 // if(dwFlags & FILE_FLAG_DELETE_ON_CLOSE
481
482 rc = DosOpen(lpFileName, &hFile, &ulAction, 0,
483 os2Attrib, os2Open, os2Flags, 0);
484
485 if(rc)
486 {
487 // TODO: TEST TEST
488 dprintf(("DosOpen Error rc:%d, try without GENERIC_WRITE", rc));
489 if(dwAccess & GENERIC_WRITE)
490 os2Flags &= ~(OPEN_ACCESS_READWRITE | OPEN_ACCESS_WRITEONLY);
491 rc = DosOpen(lpFileName, &hFile, &ulAction, 0,
492 os2Attrib, os2Open, os2Flags, 0);
493 if(rc)
494 {
495 dprintf(("DosOpen Error rc:%d os2Attrib:%X os2Open:%X os2Flags:%X",
496 rc, os2Attrib, os2Open, os2Flags));
497 hFile = -1;
498 }
499 }
500
501 *dwFile = hFile;
502 return rc;
503}
504//******************************************************************************
505//(without changing file pointer)
506//******************************************************************************
507DWORD OSLibDosGetFileSize(DWORD hFile)
508{
509 FILESTATUS3 fsts3ConfigInfo = {{0}};
510 ULONG ulBufSize = sizeof(FILESTATUS3);
511
512 DosQueryFileInfo(hFile, FIL_STANDARD, &fsts3ConfigInfo, ulBufSize);
513 return fsts3ConfigInfo.cbFile;
514}
515//******************************************************************************
516//******************************************************************************
517DWORD OSLibDosSetFilePtr2(DWORD hFile, DWORD offset, DWORD method)
518{
519 DWORD newoffset;
520 APIRET rc;
521
522
523 rc = DosSetFilePtr(hFile, offset, method, &newoffset);
524 if(rc) {
525 dprintf(("DosSetFilePtr Error rc:%d", rc));
526 return -1;
527 }
528 else return newoffset;
529}
530//******************************************************************************
531//(FlushBuffer)
532//******************************************************************************
533DWORD OSLibDosResetBuffer(DWORD hFile)
534{
535 return DosResetBuffer(hFile);
536}
537//******************************************************************************
538//******************************************************************************
539DWORD OSLibDosDupHandle(DWORD hFile, DWORD *hNew)
540{
541 *hNew = -1;
542 return DosDupHandle(hFile, hNew);
543}
544//******************************************************************************
545//******************************************************************************
546void OSLibDosDisableHardError(BOOL fTurnOff)
547{
548 DosError((fTurnOff) ? FERR_DISABLEHARDERR : FERR_ENABLEHARDERR);
549}
550//******************************************************************************
551//Returns time spent in kernel & user mode in milliseconds
552//******************************************************************************
553BOOL OSLibDosQueryProcTimes(DWORD procid, ULONG *kerneltime, ULONG *usertime)
554{
555 APIRET rc;
556 char *buf;
557 ULONG size;
558 ULONG nrthreads = 4;
559
560tryagain:
561 size = sizeof(QTOPLEVEL)+sizeof(QGLOBAL)+sizeof(QPROCESS) + nrthreads*sizeof(QTHREAD);
562 buf = (char *)malloc(size);
563 rc = DosQuerySysState(0x1, RESERVED, procid, RESERVED, (PCHAR)buf, size);
564
565 if(rc) {
566 free(buf);
567 if(rc == ERROR_BUFFER_OVERFLOW) {
568 nrthreads += 4;
569 goto tryagain;
570 }
571 return FALSE;
572 }
573 PQTOPLEVEL top = (PQTOPLEVEL)buf;
574
575 *kerneltime = 0;
576 *usertime = 0;
577 for(int i=0;i<top->procdata->threadcnt;i++) {
578 *kerneltime += top->procdata->threads[i].systime;
579 *usertime += top->procdata->threads[i].usertime;
580 }
581 free(buf);
582 return TRUE;
583}
584//******************************************************************************
585//******************************************************************************
Note: See TracBrowser for help on using the repository browser.