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

Last change on this file since 21343 was 21343, checked in by vladest, 16 years ago
  1. Increased number of handles (4096 is not enougth for some Flash animations)
  2. Added CPU cycles couter for more accurate profiling
File size: 108.9 KB
Line 
1/* $Id: oslibdos.cpp,v 1.120 2003/06/02 16:25:19 sandervl Exp $ */
2/*
3 * Wrappers for OS/2 Dos* API
4 *
5 * Copyright 1998-2000 Sander van Leeuwen (sandervl@xs4all.nl)
6 * Copyright 1999-2000 Edgar Buerkle (Edgar.Buerkle@gmx.net)
7 * Copyright 2000 Przemyslaw Dobrowolski (dobrawka@asua.org.pl)
8 * Copyright 2000 Christoph Bratschi (cbratschi@datacomm.ch)
9 * Copyright 2000 knut st. osmundsen (knut.stange.osmundsen@mynd.no)
10 *
11 * Project Odin Software License can be found in LICENSE.TXT
12 *
13 */
14
15
16
17/*******************************************************************************
18* Header Files *
19*******************************************************************************/
20#define INCL_BASE
21#define INCL_DOSEXCEPTIONS
22#define INCL_DOSMEMMGR
23#define INCL_DOSPROCESS
24#define INCL_DOSFILEMGR
25#define INCL_DOSERRORS
26#define INCL_DOSDEVIOCTL
27#define INCL_DOSDEVICES
28#define INCL_NPIPES
29#include <os2wrap.h> //Odin32 OS/2 api wrappers
30#include <stdlib.h>
31#include <stdio.h>
32#include <string.h>
33#include <ctype.h>
34#include <win32api.h>
35#include <winconst.h>
36#include <win\winioctl.h>
37#include <misc.h>
38#include "initterm.h"
39#include "oslibdos.h"
40#include "dosqss.h"
41#include "win32k.h"
42
43#define DBG_LOCALLOG DBG_oslibdos
44#include "dbglocal.h"
45
46
47/*******************************************************************************
48* Structures and Typedefs *
49*******************************************************************************/
50#ifndef DEVTYPE_OPTICAL
51#define DEVTYPE_OPTICAL 0x0008
52#endif
53
54#define IOC_CDROM_2 0x82 /* from cdioctl.h (ddk, os2cdrom.dmd sample) */
55#define IOCD_RETURN_DRIVE_LETTER 0x60
56
57
58// used for input to logical disk Get device parms Ioctl
59#pragma pack(1)
60typedef struct
61{
62 UCHAR Infotype;
63 UCHAR DriveUnit;
64} DSKREQ;
65
66/*------------------------------------------------*
67 * Cat 0x82, Func 0x60: Return Drive Letter Info *
68 *------------------------------------------------*/
69typedef struct DriveLetter_Data
70{
71 USHORT drive_count;
72 USHORT first_drive_number;
73} CDDRVLTR;
74#pragma pack()
75
76
77/*******************************************************************************
78* Global Variables *
79*******************************************************************************/
80static PROC_DosSetFileSizeL DosSetFileSizeLProc = 0;
81static PROC_DosSetFilePtrL DosSetFilePtrLProc = 0;
82static PROC_DosSetFileLocksL DosSetFileLocksLProc = 0;
83static PROC_DosOpenL DosOpenLProc = 0;
84static BOOL f64BitIO = FALSE;
85
86/* first user queries the data */
87static CDDRVLTR cdDrvLtr = {0xffff, 0xffff};
88
89
90/*******************************************************************************
91* Functions Prototypes. *
92*******************************************************************************/
93BOOL WINAPI CharToOemA( LPCSTR s, LPSTR d );
94BOOL WINAPI OemToCharA( LPCSTR s, LPSTR d );
95
96
97char* ODINHelperStripUNC(char* strUNC)
98{
99 char *retStr = strUNC;
100
101 if (!strUNC) return NULL;
102
103 /* first possible case */
104 if (strUNC[0] == '\\' &&
105 (strUNC[1] == '?' || (strUNC[1] >= 'A' && strUNC[1] <= 'Z' )) &&
106 strUNC[2] == '\\')
107 {
108
109 retStr = &strUNC[3];
110 }
111 /* second possible case */
112 if (strUNC[0] == '\\' && strUNC[1] == '\\' &&
113 (strUNC[2] == '?' || (strUNC[2] >= 'A' && strUNC[2] <= 'Z' )) &&
114 strUNC[3] == '\\')
115 {
116
117 retStr = &strUNC[4];
118 }
119 return retStr;
120}
121
122//******************************************************************************
123//******************************************************************************
124void OSLibInitWSeBFileIO()
125{
126 HMODULE hDoscalls;
127
128 if(DosQueryModuleHandle("DOSCALLS", &hDoscalls) != NO_ERROR) {
129 return;
130 }
131 if(DosQueryProcAddr(hDoscalls, 989, NULL, (PFN *)&DosSetFileSizeLProc) != NO_ERROR) {
132 return;
133 }
134 if(DosQueryProcAddr(hDoscalls, 988, NULL, (PFN *)&DosSetFilePtrLProc) != NO_ERROR) {
135 return;
136 }
137 if(DosQueryProcAddr(hDoscalls, 986, NULL, (PFN *)&DosSetFileLocksLProc) != NO_ERROR) {
138 return;
139 }
140 if(DosQueryProcAddr(hDoscalls, 981, NULL, (PFN *)&DosOpenLProc) != NO_ERROR) {
141 return;
142 }
143 f64BitIO = TRUE;
144}
145//******************************************************************************
146//******************************************************************************
147APIRET OdinDosSetFileSizeL(HFILE hFile, LONGLONG cbSize)
148{
149 APIRET yyrc;
150 USHORT sel = RestoreOS2FS();
151
152 yyrc = DosSetFileSizeLProc(hFile, cbSize);
153 SetFS(sel);
154
155 return yyrc;
156}
157//******************************************************************************
158//******************************************************************************
159APIRET OdinDosSetFilePtrL(HFILE hFile, LONGLONG ib, ULONG method, PLONGLONG ibActual)
160{
161 APIRET yyrc;
162 USHORT sel = RestoreOS2FS();
163
164 yyrc = DosSetFilePtrLProc(hFile, ib, method, ibActual);
165 SetFS(sel);
166
167 return yyrc;
168}
169//******************************************************************************
170//******************************************************************************
171APIRET OdinDosSetFileLocksL(HFILE hFile, PFILELOCKL pflUnlock, PFILELOCKL pflLock,
172 ULONG timeout, ULONG flags)
173{
174 APIRET yyrc;
175 USHORT sel = RestoreOS2FS();
176
177 yyrc = DosSetFileLocksLProc(hFile, pflUnlock, pflLock, timeout, flags);
178 SetFS(sel);
179
180 return yyrc;
181}
182//******************************************************************************
183//******************************************************************************
184APIRET APIENTRY OdinDosOpenL(PCSZ pszFileName,
185 PHFILE phf,
186 PULONG pulAction,
187 LONGLONG cbFile,
188 ULONG ulAttribute,
189 ULONG fsOpenFlags,
190 ULONG fsOpenMode,
191 PEAOP2 peaop2)
192{
193 APIRET yyrc;
194 USHORT sel = RestoreOS2FS();
195 char OemFileName[260];
196 CharToOemA(ODINHelperStripUNC((char*)pszFileName), OemFileName);
197
198 if(DosOpenLProc) {
199 yyrc = DosOpenLProc(OemFileName, phf, pulAction, cbFile, ulAttribute, fsOpenFlags,
200 fsOpenMode, peaop2);
201 }
202 else yyrc = DosOpen(OemFileName, phf, pulAction, cbFile.ulLo, ulAttribute, fsOpenFlags,
203 fsOpenMode, peaop2);
204 SetFS(sel);
205
206 return yyrc;
207}
208//******************************************************************************
209// translate OS/2 error codes to Windows codes
210// NOTE: add all codes you need, list is not complete!
211//******************************************************************************
212DWORD error2WinError(APIRET rc,DWORD defaultCode)
213{
214 switch (rc)
215 {
216 case NO_ERROR: //0
217 return ERROR_SUCCESS_W;
218
219 case ERROR_INVALID_FUNCTION: //1
220 return ERROR_INVALID_FUNCTION_W;
221
222 case ERROR_FILE_NOT_FOUND: //2
223 return ERROR_FILE_NOT_FOUND_W;
224
225 case ERROR_PATH_NOT_FOUND: //3
226 return ERROR_PATH_NOT_FOUND_W;
227
228 case ERROR_TOO_MANY_OPEN_FILES: //4
229 return ERROR_TOO_MANY_OPEN_FILES_W;
230
231 case ERROR_ACCESS_DENIED: //5
232 return ERROR_ACCESS_DENIED_W;
233
234 case ERROR_INVALID_HANDLE: //6
235 return ERROR_INVALID_HANDLE_W;
236
237 case ERROR_NOT_ENOUGH_MEMORY: //8
238 return ERROR_NOT_ENOUGH_MEMORY_W;
239
240 case ERROR_BAD_FORMAT: //11
241 return ERROR_BAD_FORMAT_W;
242
243 case ERROR_INVALID_ACCESS: //12
244 return ERROR_INVALID_ACCESS_W;
245
246 case ERROR_INVALID_DATA: //13
247 return ERROR_INVALID_DATA_W;
248
249 case ERROR_INVALID_DRIVE: //15
250 return ERROR_INVALID_DRIVE_W;
251
252 case ERROR_CURRENT_DIRECTORY: // 16
253 return ERROR_CURRENT_DIRECTORY_W;
254
255 case ERROR_NO_MORE_FILES: //18
256 return ERROR_NO_MORE_FILES_W;
257
258 case ERROR_WRITE_PROTECT: //19
259 return ERROR_WRITE_PROTECT_W;
260
261 case ERROR_BAD_UNIT: //20
262 return ERROR_BAD_UNIT_W;
263
264 case ERROR_NOT_READY: //21
265 return ERROR_NOT_READY_W;
266
267 case ERROR_CRC: //23
268 return ERROR_CRC_W;
269
270 case ERROR_SEEK:
271 return ERROR_SEEK_W;
272
273 case ERROR_NOT_DOS_DISK: //26
274 return ERROR_NOT_DOS_DISK_W;
275
276 case ERROR_WRITE_FAULT: //29
277 return ERROR_WRITE_FAULT_W;
278
279 case ERROR_GEN_FAILURE: //31
280 return ERROR_GEN_FAILURE_W;
281
282 case ERROR_SHARING_VIOLATION: //32
283 return ERROR_SHARING_VIOLATION_W;
284
285 case ERROR_LOCK_VIOLATION: //32
286 return ERROR_LOCK_VIOLATION_W;
287
288 case ERROR_WRONG_DISK: //34
289 return ERROR_WRONG_DISK_W;
290
291 case ERROR_SHARING_BUFFER_EXCEEDED: //36
292 return ERROR_SHARING_BUFFER_EXCEEDED_W;
293
294 case ERROR_BAD_NETPATH: //53
295 return ERROR_BAD_NETPATH_W;
296
297 case ERROR_CANNOT_MAKE: //82
298 return ERROR_CANNOT_MAKE_W;
299
300 case ERROR_OUT_OF_STRUCTURES: //84
301 return ERROR_OUT_OF_STRUCTURES_W;
302
303 case ERROR_INVALID_PARAMETER: //87
304 return ERROR_INVALID_PARAMETER_W;
305
306 case ERROR_INTERRUPT: //95
307 return ERROR_INVALID_AT_INTERRUPT_TIME_W; //CB: right???
308
309 case ERROR_DEVICE_IN_USE: //99
310 return ERROR_DEVICE_IN_USE_W;
311
312 case ERROR_TOO_MANY_SEMAPHORES: //100
313 return ERROR_TOO_MANY_SEMAPHORES_W;
314
315 case ERROR_DISK_CHANGE: // 107
316 return ERROR_DISK_CHANGE_W;
317
318 case ERROR_DRIVE_LOCKED: //108
319 return ERROR_DRIVE_LOCKED_W;
320
321 case ERROR_BROKEN_PIPE: //109
322 return ERROR_BROKEN_PIPE_W;
323
324 case ERROR_OPEN_FAILED: //110
325 return ERROR_OPEN_FAILED_W;
326
327 case ERROR_BUFFER_OVERFLOW: //111
328 return ERROR_BUFFER_OVERFLOW_W;
329
330 case ERROR_DISK_FULL: //112
331 return ERROR_DISK_FULL_W;
332
333 case ERROR_NO_MORE_SEARCH_HANDLES: //113
334 return ERROR_NO_MORE_SEARCH_HANDLES_W;
335
336 case ERROR_SEM_TIMEOUT: //121
337 return ERROR_SEM_TIMEOUT_W;
338
339 case ERROR_INVALID_NAME:
340 return ERROR_INVALID_NAME_W;
341
342 case ERROR_DIRECT_ACCESS_HANDLE: //130
343 return ERROR_DIRECT_ACCESS_HANDLE_W;
344
345 case ERROR_NEGATIVE_SEEK: //131
346 return ERROR_NEGATIVE_SEEK;
347
348 case ERROR_SEEK_ON_DEVICE: //132
349 return ERROR_SEEK_ON_DEVICE_W;
350
351 case ERROR_DISCARDED: //157
352 return ERROR_DISCARDED_W;
353
354 case ERROR_INVALID_EXE_SIGNATURE: // 191
355 return ERROR_INVALID_EXE_SIGNATURE_W;
356
357 case ERROR_EXE_MARKED_INVALID: // 192
358 return ERROR_EXE_MARKED_INVALID_W;
359
360 case ERROR_BAD_EXE_FORMAT: // 193
361 return ERROR_BAD_EXE_FORMAT_W;
362
363 case ERROR_FILENAME_EXCED_RANGE: //206
364 return ERROR_FILENAME_EXCED_RANGE_W;
365
366 case ERROR_META_EXPANSION_TOO_LONG: //208
367 return ERROR_META_EXPANSION_TOO_LONG_W;
368
369 case ERROR_BAD_PIPE: //230
370 return ERROR_BAD_PIPE_W;
371
372 case ERROR_PIPE_BUSY: //231
373 return ERROR_PIPE_BUSY_W;
374
375 case ERROR_NO_DATA: //232
376 return ERROR_NO_DATA_W;
377
378 case ERROR_PIPE_NOT_CONNECTED: //233
379 return ERROR_PIPE_NOT_CONNECTED_W;
380
381 case ERROR_MORE_DATA: //234
382 return ERROR_MORE_DATA_W;
383
384 case ERROR_INVALID_PATH: //253
385 return ERROR_INVALID_NAME_W;
386
387 case ERROR_INVALID_EA_NAME: //254
388 return ERROR_INVALID_EA_NAME_W;
389
390 case ERROR_EA_LIST_INCONSISTENT: //255
391 return ERROR_EA_LIST_INCONSISTENT_W;
392
393 case ERROR_EAS_DIDNT_FIT: //275
394 return ERROR_EAS_DIDNT_FIT;
395
396 // device driver specific error codes (I24)
397 case ERROR_USER_DEFINED_BASE + ERROR_I24_WRITE_PROTECT:
398 return ERROR_WRITE_PROTECT_W;
399
400 case ERROR_USER_DEFINED_BASE + ERROR_I24_BAD_UNIT:
401 return ERROR_BAD_UNIT_W;
402
403 case ERROR_USER_DEFINED_BASE + ERROR_I24_NOT_READY:
404 return ERROR_NOT_READY_W;
405
406 case ERROR_USER_DEFINED_BASE + ERROR_I24_BAD_COMMAND:
407 return ERROR_BAD_COMMAND_W;
408
409 case ERROR_USER_DEFINED_BASE + ERROR_I24_CRC:
410 return ERROR_CRC_W;
411
412 case ERROR_USER_DEFINED_BASE + ERROR_I24_BAD_LENGTH:
413 return ERROR_BAD_LENGTH_W;
414
415 case ERROR_USER_DEFINED_BASE + ERROR_I24_SEEK:
416 return ERROR_SEEK_W;
417
418 case ERROR_USER_DEFINED_BASE + ERROR_I24_NOT_DOS_DISK:
419 return ERROR_NOT_DOS_DISK_W;
420
421 case ERROR_USER_DEFINED_BASE + ERROR_I24_SECTOR_NOT_FOUND:
422 return ERROR_SECTOR_NOT_FOUND_W;
423
424// @@@PH this error code is not defined in winconst.h
425// case ERROR_USER_DEFINED_BASE + ERROR_I24_OUT_OF_PAPER:
426// return 28;
427
428 case ERROR_USER_DEFINED_BASE + ERROR_I24_WRITE_FAULT:
429 return ERROR_WRITE_FAULT_W;
430
431 case ERROR_USER_DEFINED_BASE + ERROR_I24_READ_FAULT:
432 return ERROR_READ_FAULT_W;
433
434 case ERROR_USER_DEFINED_BASE + ERROR_I24_GEN_FAILURE:
435 return ERROR_GEN_FAILURE_W;
436
437 case ERROR_USER_DEFINED_BASE + ERROR_I24_DISK_CHANGE:
438 return ERROR_DISK_CHANGE_W;
439
440 case ERROR_USER_DEFINED_BASE + ERROR_I24_WRONG_DISK:
441 return ERROR_WRONG_DISK_W;
442
443 case ERROR_USER_DEFINED_BASE + ERROR_I24_INVALID_PARAMETER:
444 return ERROR_INVALID_PARAMETER_W;
445
446 case ERROR_USER_DEFINED_BASE + ERROR_I24_DEVICE_IN_USE:
447 return ERROR_DEVICE_IN_USE_W;
448
449 default:
450 dprintf(("WARNING: error2WinError: error %d not included!!!!", rc));
451 return defaultCode;
452 }
453}
454//******************************************************************************
455//******************************************************************************
456DWORD OSLibDosOpen(char *lpszFileName, DWORD flags)
457{
458 APIRET rc;
459 HFILE hFile;
460 ULONG ulAction;
461 DWORD os2flags = OPEN_FLAGS_NOINHERIT; //default is not inherited by child processes
462 char lOemFileName[260];
463
464 CharToOemA(ODINHelperStripUNC(lpszFileName), lOemFileName);
465
466 if(flags & OSLIB_ACCESS_READONLY)
467 os2flags |= OPEN_ACCESS_READONLY;
468 else
469 if(flags & OSLIB_ACCESS_READWRITE)
470 os2flags |= OPEN_ACCESS_READWRITE;
471
472 if(flags & OSLIB_ACCESS_SHAREDENYNONE)
473 os2flags |= OPEN_SHARE_DENYNONE;
474 else
475 if(flags & OSLIB_ACCESS_SHAREDENYREAD)
476 os2flags |= OPEN_SHARE_DENYREAD;
477 else
478 if(flags & OSLIB_ACCESS_SHAREDENYWRITE)
479 os2flags |= OPEN_SHARE_DENYWRITE;
480
481tryopen:
482 rc = DosOpen(lOemFileName, /* File path name */
483 &hFile, /* File handle */
484 &ulAction, /* Action taken */
485 0L, /* File primary allocation */
486 0L, /* File attribute */
487 OPEN_ACTION_FAIL_IF_NEW |
488 OPEN_ACTION_OPEN_IF_EXISTS, /* Open function type */
489 os2flags,
490 0L); /* No extended attribute */
491 if(rc)
492 {
493 if(rc == ERROR_TOO_MANY_OPEN_FILES)
494 {
495 ULONG CurMaxFH;
496 LONG ReqCount = 32;
497
498 rc = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
499 if(rc)
500 {
501 dprintf(("DosSetRelMaxFH returned %d", rc));
502 return 0;
503 }
504 dprintf(("DosOpen failed -> increased nr open files to %d", CurMaxFH));
505 goto tryopen;
506 }
507
508 SetLastError(error2WinError(rc));
509 return 0;
510 }
511
512 // OK, file was opened
513 SetLastError(ERROR_SUCCESS_W);
514 return hFile;
515}
516//******************************************************************************
517//******************************************************************************
518BOOL OSLibDosClose(DWORD hFile)
519{
520 APIRET rc;
521
522 rc = DosClose(hFile);
523 SetLastError(error2WinError(rc));
524 return (rc == NO_ERROR);
525}
526//******************************************************************************
527//******************************************************************************
528BOOL OSLibDosCopyFile(LPCSTR lpszOldFile, LPCSTR lpszNewFile, BOOL fFailIfExist)
529{
530 APIRET rc;
531 char lOemOldFile[260], lOemNewFile[260];
532
533 CharToOemA(ODINHelperStripUNC((char*)lpszOldFile), lOemOldFile);
534 CharToOemA(ODINHelperStripUNC((char*)lpszNewFile), lOemNewFile);
535
536 rc = DosCopy((PSZ)lOemOldFile, (PSZ)lOemNewFile, fFailIfExist ? 0: DCPY_EXISTING);
537 SetLastError(error2WinError(rc));
538 return (rc == NO_ERROR);
539}
540//******************************************************************************
541//******************************************************************************
542BOOL OSLibDosMoveFile(LPCSTR lpszOldFile, LPCSTR lpszNewFile)
543{
544 APIRET rc;
545 char lOemOldFile[260], lOemNewFile[260];
546
547 CharToOemA(ODINHelperStripUNC((char*)lpszOldFile), lOemOldFile);
548 CharToOemA(ODINHelperStripUNC((char*)lpszNewFile), lOemNewFile);
549
550 // we need to know the current drive for relative paths
551 ULONG diskNum, logicalBitmap;
552 DosQueryCurrentDisk(&diskNum, &logicalBitmap);
553 char currentDrive = 'A' + diskNum - 1;
554
555 // first determine whether source and target paths are absolute
556 // (i.e. contain a drive letter)
557 BOOL sourcePathAbsolute = FALSE;
558 char sourceDrive = currentDrive;
559 if ((strlen(lOemOldFile) > 2) && (lOemOldFile[1] == ':'))
560 {
561 sourcePathAbsolute = TRUE;
562 sourceDrive = toupper(lOemOldFile[0]);
563 }
564 BOOL targetPathAbsolute = FALSE;
565 char targetDrive = currentDrive;
566 if ((strlen(lOemNewFile) > 2) && (lOemNewFile[1] == ':'))
567 {
568 targetPathAbsolute = TRUE;
569 targetDrive = toupper(lOemNewFile[0]);
570 }
571
572 // if the source and target drives are different, we have to do take
573 // the copy and delete path
574 if (sourceDrive != targetDrive)
575 {
576 dprintf(("OSLibDosMoveFile - different drives, doing the copy/delete approach (WARNING: non atomic file system operation!)"));
577 // @@@AH TODO: this is not atomic. Maybe it is on Windows - we have to check this
578 rc = DosCopy((PSZ)lOemOldFile, (PSZ)lOemNewFile, 0);
579 if (rc == NO_ERROR)
580 {
581 rc = DosDelete(lOemOldFile);
582 }
583 SetLastError(error2WinError(rc));
584 } else
585 {
586 // atomic DosMove will do fine
587 rc = DosMove((PSZ)lOemOldFile, (PSZ)lOemNewFile);
588 SetLastError(error2WinError(rc));
589 }
590 return (rc == NO_ERROR);
591}
592//******************************************************************************
593//******************************************************************************
594BOOL OSLibDosRemoveDir(LPCSTR lpszDir)
595{
596 APIRET rc;
597 char lOemDir[260];
598
599 CharToOemA(ODINHelperStripUNC((char*)lpszDir), lOemDir);
600
601 rc = DosDeleteDir((PSZ)lOemDir);
602 SetLastError(error2WinError(rc));
603 return (rc == NO_ERROR);
604}
605//******************************************************************************
606//******************************************************************************
607BOOL OSLibDosCreateDirectory(LPCSTR lpszDir)
608{
609 APIRET rc;
610 char lOemDir[260];
611
612 CharToOemA(ODINHelperStripUNC((char*)lpszDir), lOemDir);
613
614 rc = DosCreateDir((PSZ)lOemDir, NULL);
615 SetLastError(error2WinError(rc));
616 return (rc == NO_ERROR);
617}
618//******************************************************************************
619//******************************************************************************
620DWORD OSLibDosChangeMaxFileHandles()
621{
622 ULONG CurMaxFH;
623 LONG ReqCount = 0;
624 APIRET rc;
625
626 rc = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
627 if(rc) {
628 dprintf(("DosSetRelMaxFH returned %d", rc));
629 return rc;
630 }
631 if(ReqCount + ODIN_INCREMENT_MAX_FILEHANDLES > CurMaxFH) {
632 ReqCount = CurMaxFH + ODIN_INCREMENT_MAX_FILEHANDLES;
633 rc = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
634 if(rc) {
635 dprintf(("DosSetRelMaxFH returned %d", rc));
636 return rc;
637 }
638 }
639 return 0;
640}
641//******************************************************************************
642//******************************************************************************
643DWORD OSLibDosSetInitialMaxFileHandles(DWORD maxhandles)
644{
645 ULONG CurMaxFH;
646 LONG ReqCount = 0;
647 APIRET rc;
648
649 rc = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
650 if(rc) {
651 dprintf(("DosSetRelMaxFH returned %d", rc));
652 return rc;
653 }
654 if(CurMaxFH < maxhandles) {
655 rc = DosSetMaxFH(maxhandles);
656 if(rc) {
657 dprintf(("DosSetMaxFH returned %d", rc));
658 return rc;
659 }
660 }
661 return 0;
662}
663//******************************************************************************
664//******************************************************************************
665BOOL OSLibDosRead(DWORD hFile, LPVOID lpBuffer, DWORD size, DWORD *nrBytesRead)
666{
667 APIRET rc;
668
669 rc = DosRead(hFile, lpBuffer, size, nrBytesRead);
670 SetLastError(error2WinError(rc));
671 return (rc == NO_ERROR);
672}
673//******************************************************************************
674//******************************************************************************
675BOOL OSLibDosWrite(DWORD hFile, LPVOID lpBuffer, DWORD size, DWORD *nrBytesWritten)
676{
677 APIRET rc;
678
679 rc = DosWrite(hFile, lpBuffer, size, nrBytesWritten);
680 SetLastError(error2WinError(rc));
681 return (rc == NO_ERROR);
682}
683//******************************************************************************
684//******************************************************************************
685DWORD OSLibDosSetFilePtr(DWORD hFile, DWORD offset, DWORD method)
686{
687 DWORD os2method;
688 DWORD newoffset;
689 APIRET rc;
690
691 switch(method)
692 {
693 case OSLIB_SETPTR_FILE_CURRENT:
694 os2method = FILE_CURRENT;
695 break;
696 case OSLIB_SETPTR_FILE_BEGIN:
697 os2method = FILE_BEGIN ;
698 break;
699 case OSLIB_SETPTR_FILE_END:
700 os2method = FILE_END;
701 break;
702 default:
703 return OSLIB_ERROR_INVALID_PARAMETER;
704 }
705
706 rc = DosSetFilePtr(hFile, offset, os2method, &newoffset);
707 if(rc)
708 {
709 SetLastError(error2WinError(rc));
710 return -1;
711 }
712 SetLastError(ERROR_SUCCESS_W);
713 return newoffset;
714}
715//******************************************************************************
716//******************************************************************************
717BOOL OSLibDosDelete(char *lpszFileName)
718{
719 APIRET rc;
720 char lOemFileName[260];
721
722 CharToOemA(ODINHelperStripUNC(lpszFileName), lOemFileName);
723
724 rc = DosDelete(lOemFileName);
725 if(rc) {
726 SetLastError(error2WinError(rc));
727 return FALSE;
728 }
729 return TRUE;
730}
731//******************************************************************************
732//******************************************************************************
733BOOL pmDateTimeToFileTime(FDATE *pDate,FTIME *pTime,FILETIME *pFT)
734{
735 USHORT dosTime, dosDate;
736 BOOL ret;
737 FILETIME dummy;
738
739 dosTime = *(USHORT*)pTime;
740 dosDate = *(USHORT*)pDate;
741
742 //time we get from OS2 is local time; win32 expects file time (UTC)
743 ret = DosDateTimeToFileTime(dosDate, dosTime, &dummy);
744 if(ret) ret = LocalFileTimeToFileTime(&dummy, pFT);
745 return ret;
746}
747//******************************************************************************
748//******************************************************************************
749BOOL pmFileTimeToDateTime(FILETIME *pFT, FDATE *pDate, FTIME *pTime)
750{
751 BOOL ret;
752 FILETIME dummy;
753 //time we get from win32 is file time (UTC); OS2 expects local time
754 ret = FileTimeToLocalFileTime(pFT, &dummy);
755 if (ret) ret = FileTimeToDosDateTime(&dummy, (WORD*)pDate, (WORD*)pTime);
756 return ret;
757}
758//******************************************************************************
759//******************************************************************************
760#define NOT_NORMAL (FILE_ATTRIBUTE_READONLY_W | \
761 FILE_ATTRIBUTE_HIDDEN_W | \
762 FILE_ATTRIBUTE_SYSTEM_W | \
763 FILE_ATTRIBUTE_ARCHIVE_W)
764
765inline DWORD pm2WinFileAttributes(DWORD attrFile)
766{
767 DWORD res = 0;
768
769 if (!(attrFile & NOT_NORMAL))
770 res |= FILE_ATTRIBUTE_NORMAL_W;
771 if (attrFile & FILE_READONLY)
772 res |= FILE_ATTRIBUTE_READONLY_W;
773 if (attrFile & FILE_HIDDEN)
774 res |= FILE_ATTRIBUTE_HIDDEN_W;
775 if (attrFile & FILE_SYSTEM)
776 res |= FILE_ATTRIBUTE_SYSTEM_W;
777 if (attrFile & FILE_DIRECTORY)
778 res |= FILE_ATTRIBUTE_DIRECTORY_W;
779 if (attrFile & FILE_ARCHIVED)
780 res |= FILE_ATTRIBUTE_ARCHIVE_W;
781
782 //CB: not used: FILE_ATTRIBUTE_COMPRESSED_W
783 //PH: NT server will serve appropriate sizes for compressed files
784 // over network. So if realSize < allocatedSize, the file must
785 // be compressed.
786
787 return res;
788}
789//******************************************************************************
790//******************************************************************************
791BOOL OSLibDosGetFileAttributesEx(PSZ pszName,
792 ULONG ulDummy,
793 PVOID pBuffer)
794{
795 APIRET rc; /* API return code */
796 FILESTATUS3 fs3; /* file information structure */
797 LPWIN32_FILE_ATTRIBUTE_DATA lpFad = (LPWIN32_FILE_ATTRIBUTE_DATA) pBuffer;
798
799 // Note: we only handle standard "GetFileExInfoStandard" requests
800 rc = DosQueryPathInfo(ODINHelperStripUNC(pszName), /* query the file information */
801 FIL_STANDARD,
802 &fs3,
803 sizeof(fs3));
804 if (rc != NO_ERROR) /* check for errors */
805 return FALSE; /* raise error condition */
806
807 // convert structure
808 lpFad->dwFileAttributes = pm2WinFileAttributes(fs3.attrFile);
809 pmDateTimeToFileTime(&fs3.fdateCreation, &fs3.ftimeCreation, &lpFad->ftCreationTime);
810 pmDateTimeToFileTime(&fs3.fdateLastAccess, &fs3.ftimeLastAccess, &lpFad->ftLastAccessTime);
811 pmDateTimeToFileTime(&fs3.fdateLastWrite, &fs3.ftimeLastWrite, &lpFad->ftLastWriteTime);
812
813 /* @@@PH we might add Aurora support ...
814 lpFad->nFileSizeHigh = info.nFileSizeHigh;
815 */
816 lpFad->nFileSizeHigh = 0;
817 lpFad->nFileSizeLow = fs3.cbFile;
818
819 return TRUE;
820}
821//******************************************************************************
822DWORD WIN32API GetEnvironmentVariableA(LPCSTR, LPSTR, DWORD );
823//******************************************************************************
824DWORD OSLibDosSearchPath(DWORD cmd, char *path, char *name, char *full_name,
825 DWORD length_fullname)
826{
827 switch(cmd) {
828 case OSLIB_SEARCHDIR:
829 if(DosSearchPath(SEARCH_IGNORENETERRS, ODINHelperStripUNC(path),
830 name, full_name, length_fullname) != 0) {
831 return 0;
832 }
833 return strlen(full_name);
834
835
836 case OSLIB_SEARCHCURDIR:
837 if(DosSearchPath(SEARCH_IGNORENETERRS | SEARCH_CUR_DIRECTORY, ODINHelperStripUNC(path),
838 name, full_name, length_fullname) != 0) {
839 return 0;
840 }
841 return strlen(full_name);
842
843 case OSLIB_SEARCHFILE:
844 {
845 FILESTATUS3 fileinfo;
846
847 if(DosQueryPathInfo(ODINHelperStripUNC(name), FIL_STANDARD, &fileinfo, sizeof(fileinfo)) != 0) {
848 return 0;
849 }
850 strncpy(full_name, name, length_fullname);
851 full_name[length_fullname-1] = 0;
852 return strlen(full_name);
853 }
854
855 case OSLIB_SEARCHENV:
856 {
857 LPSTR envstring;
858 int envsize;
859 CHAR szResult[CCHMAXPATH];
860
861 envsize = GetEnvironmentVariableA(path, NULL, 0);
862 envstring = (LPSTR)malloc(envsize+1);
863 GetEnvironmentVariableA(path, envstring, envsize);
864 if(DosSearchPath(SEARCH_IGNORENETERRS, envstring,
865 name, szResult, sizeof(szResult)) != 0) {
866 free(envstring);
867 return 0;
868 }
869 free(envstring);
870 strcpy(full_name, szResult);
871 return strlen(full_name);
872 }
873 }
874 return 0;
875}
876//******************************************************************************
877//******************************************************************************
878DWORD OSLibDosQueryPathInfo(CHAR *pszPathName,
879 ULONG ulInfoLevel,
880 PVOID pInfoBuf,
881 ULONG cbInfoBuf)
882{
883 APIRET rc = DosQueryPathInfo( ODINHelperStripUNC(pszPathName), ulInfoLevel,
884 pInfoBuf, cbInfoBuf );
885
886 if(rc == ERROR_TOO_MANY_OPEN_FILES)
887 {
888 LONG reqCount = 2;
889 ULONG maxFiles;
890
891 if(DosSetRelMaxFH(&reqCount, &maxFiles) == NO_ERROR)
892 rc = DosQueryPathInfo(pszPathName, ulInfoLevel,
893 pInfoBuf, cbInfoBuf );
894 }
895 return rc;
896}
897//******************************************************************************
898//******************************************************************************
899DWORD OSLibDosCreateFile(CHAR *lpszFile,
900 DWORD fuAccess,
901 DWORD fuShare,
902 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
903 DWORD fuCreate,
904 DWORD fuAttrFlags,
905 HANDLE hTemplateFile)
906{
907 HFILE hFile;
908 ULONG actionTaken = 0;
909 LONGLONG fileSize = {0};
910 ULONG fileAttr = FILE_NORMAL;
911 ULONG openFlag = 0;
912 ULONG openMode = OPEN_FLAGS_NOINHERIT; //default is not inherited by child processes
913 APIRET rc = ERROR_NOT_ENOUGH_MEMORY;
914
915 CHAR* lpszFileLoc = ODINHelperStripUNC(lpszFile);
916
917 //TODO: lpSecurityAttributes (inheritance)
918
919 if(fuAttrFlags & FILE_ATTRIBUTE_ARCHIVE_W)
920 fileAttr |= FILE_ARCHIVED;
921 if(fuAttrFlags & FILE_ATTRIBUTE_HIDDEN_W)
922 fileAttr |= FILE_HIDDEN;
923 if(fuAttrFlags & FILE_ATTRIBUTE_SYSTEM_W)
924 fileAttr |= FILE_SYSTEM;
925 if(fuAttrFlags & FILE_ATTRIBUTE_READONLY_W)
926 fileAttr |= FILE_READONLY;
927 // TODO: FILE_ATTRIBUTE_TEMPORARY_W
928
929 switch(fuCreate)
930 {
931 case CREATE_NEW_W:
932 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_FAIL_IF_EXISTS;
933 break;
934 case CREATE_ALWAYS_W:
935 /* kso 2000-11-26: Not sure if OPEN_ACTION_REPLACE_IF_EXISTS is correct here! It is correct according to
936 * MSDN, but not according to "The Win32 API SuperBible". Anyway I haven't got time to check it out in
937 * NT now.
938 * The problem is that OPEN_ACTION_REPLACE_IF_EXISTS requires write access. It failes with
939 * rc = ERROR_ACCESS_DENIED (5). Quick fix, use OPEN_IF_EXIST if readonly access.
940 */
941 if (fuAccess & GENERIC_WRITE_W)
942 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
943 else
944 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
945 break;
946 case OPEN_EXISTING_W:
947 openFlag |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
948 break;
949 case OPEN_ALWAYS_W:
950 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
951 break;
952 case TRUNCATE_EXISTING_W:
953 openFlag |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
954 break;
955 }
956
957 if(fuAttrFlags & FILE_FLAG_WRITE_THROUGH_W) openMode |= OPEN_FLAGS_WRITE_THROUGH;
958 if(fuAttrFlags & FILE_FLAG_NO_BUFFERING_W) openMode |= OPEN_FLAGS_NO_CACHE;
959 if(fuAttrFlags & FILE_FLAG_RANDOM_ACCESS_W) openMode |= OPEN_FLAGS_RANDOM;
960 if(fuAttrFlags & FILE_FLAG_SEQUENTIAL_SCAN_W) openMode |= OPEN_FLAGS_SEQUENTIAL;
961 // TODO: FILE_FLAG_BACKUP_SEMANTICS_W
962 // FILE_FLAG_POSIX_SEMANTICS_W are not supported
963
964 //TODO: FILE_SHARE_DELETE
965 if((fuShare & (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W)) == 0 )
966 openMode |= OPEN_SHARE_DENYREADWRITE;
967 else
968 if((fuShare & (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W)) == (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W))
969 openMode |= OPEN_SHARE_DENYNONE;
970 else
971 if(fuShare & FILE_SHARE_READ_W)
972 openMode |= OPEN_SHARE_DENYWRITE;
973 else
974 if(fuShare & FILE_SHARE_WRITE_W)
975 openMode |= OPEN_SHARE_DENYREAD;
976
977 if(fuAccess == (GENERIC_READ_W | GENERIC_WRITE_W))
978 openMode |= OPEN_ACCESS_READWRITE;
979 else
980 if(fuAccess & GENERIC_READ_W)
981 openMode |= OPEN_ACCESS_READONLY;
982 else
983 //mgp: There seems to be a problem where OPEN_ACCESS_WRITEONLY gives an
984 // Access Error (0x05) if the file is opened with
985 // OPEN_ACTION_OPEN_IF_EXISTS. So, in that case, change it to
986 // OPEN_ACCESS_READWRITE
987 if(fuAccess & GENERIC_WRITE_W)
988 if (openFlag & OPEN_ACTION_OPEN_IF_EXISTS)
989 openMode |= OPEN_ACCESS_READWRITE;
990 else
991 openMode |= OPEN_ACCESS_WRITEONLY;
992
993#if 0
994 //SvL: Not true; verified in NT! (also messed up access of files on
995 // readonly volumes)
996 // CreateFile with OPEN_ALWAYS & GENERIC_READ on non-existing file
997 // -> creates 0 size file, WriteFile is not allowed
998 // Same in OS/2.
999 /* if creating a file, access cannot be readonly! */
1000 if (openFlag & OPEN_ACTION_CREATE_IF_NEW &&
1001 (!(openMode & OPEN_ACCESS_READWRITE) &&
1002 !(openMode & OPEN_ACCESS_WRITEONLY))) {
1003 openMode |= OPEN_ACCESS_READWRITE;
1004 }
1005#endif
1006
1007 if(strlen(lpszFileLoc) == 2 && lpszFileLoc[1] == ':') {
1008 //app tries to open logical volume/partition
1009 openMode |= OPEN_FLAGS_DASD;
1010 }
1011
1012 int retry = 0;
1013 while (retry < 3)
1014 {
1015 dprintf(("DosOpen %s openFlag=%x openMode=%x", lpszFileLoc, openFlag, openMode));
1016 rc = OdinDosOpenL((PSZ)lpszFileLoc,
1017 &hFile,
1018 &actionTaken,
1019 fileSize,
1020 fileAttr,
1021 openFlag,
1022 openMode,
1023 NULL);
1024 if (rc == ERROR_TOO_MANY_OPEN_FILES)
1025 {
1026 ULONG CurMaxFH;
1027 LONG ReqCount = 32;
1028
1029 rc = DosSetRelMaxFH(&ReqCount, &CurMaxFH);
1030 if(rc) {
1031 dprintf(("DosSetRelMaxFH returned %d", rc));
1032 SetLastError(ERROR_TOO_MANY_OPEN_FILES_W);
1033 return INVALID_HANDLE_VALUE_W;
1034 }
1035 dprintf(("DosOpen failed -> increased nr open files to %d", CurMaxFH));
1036 }
1037 #if 0
1038 else if (rc == ERROR_ACCESS_DENIED && (openFlag & OPEN_ACTION_REPLACE_IF_EXISTS))
1039 { /* kso: I have great problems with the REPLACE not working
1040 * So, I guess this emulation may help...
1041 * This problem exist on WS4eB SMP FP1 and Warp4 FP14/Kernel 14059 at least.
1042 */
1043 rc = DosOpen((PSZ)lOemFile,
1044 &hFile,
1045 &actionTaken,
1046 fileSize,
1047 fileAttr,
1048 (openFlag & ~OPEN_ACTION_REPLACE_IF_EXISTS) | OPEN_ACTION_OPEN_IF_EXISTS,
1049 openMode,
1050 NULL);
1051 if (rc == NO_ERROR)
1052 {
1053 rc = DosSetFileSize(hFile, 0);
1054 if (!rc && fileSize > 0)
1055 rc = DosSetFileSize(hFile, fileSize);
1056 if (rc)
1057 {
1058 DosClose(hFile);
1059 hFile = NULLHANDLE;
1060
1061 if (rc != ERROR_TOO_MANY_OPEN_FILES)
1062 break;
1063 }
1064 else break;
1065 }
1066 }
1067 #endif
1068 else break;
1069 retry++;
1070 }
1071
1072 if(rc)
1073 {
1074 // @@@AH 2001-06-02 Win2k SP2 returns error 2 in this case
1075 int winError = error2WinError(rc);
1076 if (winError == ERROR_OPEN_FAILED_W || winError == ERROR_PATH_NOT_FOUND_W)
1077 {
1078 //Windows returns ERROR_FILE_EXISTS if create new & file exists
1079 if(fuCreate == CREATE_NEW_W) {
1080 winError = ERROR_FILE_EXISTS_W;
1081 }
1082 else winError = ERROR_FILE_NOT_FOUND_W;
1083 }
1084 SetLastError(winError);
1085 return INVALID_HANDLE_VALUE_W;
1086 }
1087 SetLastError(ERROR_SUCCESS_W);
1088 return hFile;
1089}
1090//******************************************************************************
1091//******************************************************************************
1092DWORD OSLibDosOpenFile(CHAR *lpszFile, UINT fuMode)
1093{
1094 ULONG actionTaken = 0;
1095 LONGLONG fileSize = {0};
1096 ULONG fileAttr = FILE_NORMAL;
1097 ULONG openFlag = 0;
1098 ULONG openMode = OPEN_FLAGS_NOINHERIT; //default is not inherited by child processes
1099 APIRET rc = ERROR_NOT_ENOUGH_MEMORY;
1100 HFILE hFile;
1101
1102 if(!(fuMode & (OF_CREATE_W | OF_READWRITE_W | OF_WRITE_W)))
1103 {
1104 openMode |= OPEN_ACCESS_READONLY;
1105 openFlag |= OPEN_ACTION_OPEN_IF_EXISTS;
1106 }
1107 else
1108 {
1109 if(fuMode & OF_CREATE_W) {
1110 openFlag |= OPEN_ACTION_CREATE_IF_NEW |
1111 OPEN_ACTION_REPLACE_IF_EXISTS;
1112 }
1113 else openFlag |= OPEN_ACTION_OPEN_IF_EXISTS;
1114
1115 if(fuMode & OF_READWRITE_W)
1116 openMode |= OPEN_ACCESS_READWRITE;
1117 else
1118 if(fuMode & OF_WRITE_W)
1119 openMode |= OPEN_ACCESS_WRITEONLY;
1120 else
1121 if(fuMode & OF_CREATE_W)
1122 openMode |= OPEN_ACCESS_READWRITE;
1123 }
1124
1125 if((fuMode & OF_SHARE_DENY_WRITE_W) ||
1126 !(fuMode & (OF_SHARE_DENY_READ_W | OF_SHARE_DENY_NONE_W | OF_SHARE_EXCLUSIVE_W)))
1127 openMode |= OPEN_SHARE_DENYWRITE;
1128 else
1129 if (fuMode & OF_SHARE_DENY_NONE_W)
1130 openMode |= OPEN_SHARE_DENYNONE;
1131 else
1132 if (fuMode & OF_SHARE_DENY_READ_W)
1133 openMode |= OPEN_SHARE_DENYREAD;
1134 else
1135 if (fuMode & OF_SHARE_EXCLUSIVE_W)
1136 openMode |= OPEN_SHARE_DENYREADWRITE;
1137
1138 rc = OdinDosOpenL((PSZ)lpszFile,
1139 &hFile,
1140 &actionTaken,
1141 fileSize,
1142 fileAttr,
1143 openFlag,
1144 openMode,
1145 NULL);
1146
1147 if(rc != NO_ERROR)
1148 {
1149 if(fuMode & OF_EXIST_W)
1150 {
1151 if(rc == ERROR_OPEN_FAILED || rc == ERROR_FILE_NOT_FOUND)
1152 {
1153 SetLastError(ERROR_FILE_NOT_FOUND_W);
1154 return HFILE_ERROR_W;
1155 }
1156 }
1157 if((rc == ERROR_OPEN_FAILED) && (openFlag & OPEN_ACTION_OPEN_IF_EXISTS))
1158 {
1159 SetLastError(ERROR_FILE_NOT_FOUND_W);
1160 }
1161 else SetLastError(error2WinError(rc));
1162
1163 return HFILE_ERROR_W;
1164 }
1165 SetLastError(ERROR_SUCCESS_W);
1166 return hFile;
1167}
1168//******************************************************************************
1169//******************************************************************************
1170BOOL OSLibDosLockFile(DWORD hFile, DWORD dwFlags,
1171 DWORD OffsetLow, DWORD OffsetHigh,
1172 DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh,
1173 LPOVERLAPPED lpOverlapped)
1174{
1175 APIRET rc;
1176
1177 // Set 5 secs timeout for locking file and no other can access this
1178 // file region
1179
1180 if(lpOverlapped) {//TODO:
1181 dprintf(("OSLibDosLockFile: overlapped lock not yet implemented!!"));
1182 }
1183 //TODO: Locking region crossing end of file is permitted. Works in OS/2??
1184 if(f64BitIO)
1185 {
1186 FILELOCKL lockRangeL;
1187
1188 lockRangeL.lOffset.ulLo = OffsetLow;
1189 lockRangeL.lOffset.ulHi = OffsetHigh;
1190 lockRangeL.lRange.ulLo = nNumberOfBytesToLockLow;
1191 lockRangeL.lRange.ulHi = nNumberOfBytesToLockHigh;
1192
1193 rc = OdinDosSetFileLocksL(hFile, NULL, &lockRangeL,
1194 (dwFlags & LOCKFILE_FAIL_IMMEDIATELY_W) ? 0 : 5000, 0);
1195 //SvL: 64 bits values are only supported by JFS
1196 // Try the 32 bits DosSetFileLocks if it fails
1197 // (TODO: should check the partition type instead)
1198 if(rc == ERROR_INVALID_PARAMETER && (OffsetHigh || nNumberOfBytesToLockHigh)) {
1199 goto oldlock;
1200 }
1201 }
1202 else
1203 {
1204oldlock:
1205 FILELOCK lockRange = { OffsetLow, nNumberOfBytesToLockLow };
1206
1207 rc = DosSetFileLocks(hFile, NULL, &lockRange,
1208 (dwFlags & LOCKFILE_FAIL_IMMEDIATELY_W) ? 0 : 5000, 0);
1209 }
1210 if(rc) {
1211 SetLastError(error2WinError(rc));
1212 return FALSE;
1213 }
1214 SetLastError(ERROR_SUCCESS_W);
1215 return TRUE;
1216}
1217//******************************************************************************
1218//******************************************************************************
1219BOOL OSLibDosUnlockFile(DWORD hFile, DWORD OffsetLow, DWORD OffsetHigh,
1220 DWORD nNumberOfBytesToLockLow, DWORD nNumberOfBytesToLockHigh,
1221 LPOVERLAPPED lpOverlapped)
1222{
1223 APIRET rc;
1224
1225 // Set 5 secs timeout for unlocking file and no other can access this
1226 // file region
1227
1228 if(lpOverlapped) {//TODO:
1229 dprintf(("OSLibDosUnlockFile: overlapped unlock not yet implemented!!"));
1230 }
1231 if(f64BitIO)
1232 {
1233 FILELOCKL unlockRangeL;
1234
1235 unlockRangeL.lOffset.ulLo = OffsetLow;
1236 unlockRangeL.lOffset.ulHi = OffsetHigh;
1237 unlockRangeL.lRange.ulLo = nNumberOfBytesToLockLow;
1238 unlockRangeL.lRange.ulHi = nNumberOfBytesToLockHigh;
1239
1240 rc = OdinDosSetFileLocksL(hFile, &unlockRangeL, NULL, 5000, 0);
1241 //SvL: 64 bits values are only supported by JFS
1242 // Try the 32 bits DosSetFileLocks if it fails
1243 // (TODO: should check the partition type instead)
1244 if(rc == ERROR_INVALID_PARAMETER && (OffsetHigh || nNumberOfBytesToLockHigh)) {
1245 goto oldlock;
1246 }
1247 }
1248 else
1249 {
1250oldlock:
1251 FILELOCK unlockRange = { OffsetLow, nNumberOfBytesToLockLow };
1252
1253 rc = DosSetFileLocks(hFile, &unlockRange, NULL, 5000, 0);
1254 }
1255 if(rc) {
1256 SetLastError(error2WinError(rc));
1257 return FALSE;
1258 }
1259 SetLastError(ERROR_SUCCESS_W);
1260 return TRUE;
1261}
1262//******************************************************************************
1263//******************************************************************************
1264BOOL OSLibDosFlushFileBuffers(DWORD hFile)
1265{
1266 APIRET rc;
1267
1268 rc = DosResetBuffer(hFile);
1269 SetLastError(error2WinError(rc));
1270 return (rc == NO_ERROR);
1271}
1272//******************************************************************************
1273//******************************************************************************
1274DWORD OSLibDosGetFileSize(DWORD hFile, LPDWORD lpdwFileSizeHigh)
1275{
1276 APIRET rc;
1277 ULONG sizeLow;
1278
1279 if(f64BitIO)
1280 {
1281 FILESTATUS3L fsts3ConfigInfoL = {{0}};
1282 ULONG ulBufSize = sizeof(FILESTATUS3L);
1283
1284 rc = DosQueryFileInfo(hFile, FIL_STANDARDL, &fsts3ConfigInfoL, ulBufSize);
1285 if(lpdwFileSizeHigh) {
1286 *lpdwFileSizeHigh = fsts3ConfigInfoL.cbFile.ulHi;
1287 }
1288 sizeLow = fsts3ConfigInfoL.cbFile.ulLo;
1289 }
1290 else
1291 {
1292 FILESTATUS3 fsts3ConfigInfo = {{0}};
1293 ULONG ulBufSize = sizeof(FILESTATUS3);
1294
1295 if(lpdwFileSizeHigh) {
1296 *lpdwFileSizeHigh = 0;
1297 }
1298 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &fsts3ConfigInfo, ulBufSize);
1299 sizeLow = fsts3ConfigInfo.cbFile;
1300 }
1301 if(rc) {
1302 SetLastError(error2WinError(rc));
1303 return -1;
1304 }
1305 SetLastError(ERROR_SUCCESS_W);
1306 return sizeLow;
1307}
1308//******************************************************************************
1309//******************************************************************************
1310DWORD OSLibDosSetFilePointer(DWORD hFile, DWORD OffsetLow, DWORD *OffsetHigh, DWORD method)
1311{
1312 LONGLONG offsetL;
1313 LONGLONG newoffsetL;
1314 APIRET rc;
1315 DWORD newoffset;
1316
1317 switch(method)
1318 {
1319 case FILE_BEGIN_W:
1320 method = FILE_BEGIN;
1321 break;
1322
1323 case FILE_CURRENT_W:
1324 method = FILE_CURRENT;
1325 break;
1326
1327 case FILE_END_W:
1328 method = FILE_END;
1329 break;
1330 }
1331
1332 // PH Note: for a negative 32-bit seek, the OS/2 64-bit version
1333 // needs to be skipped.
1334#if 0 /* doesnt works at all with flash 10 */
1335 if( (f64BitIO) && (OffsetHigh) && ((DWORD)OffsetHigh != 0xAAAAAAAA) &&
1336 (*OffsetHigh != 0xAAAAAAAA) &&
1337 (*OffsetHigh != 0)) //workaround for flash10 video
1338 {
1339 offsetL.ulLo = OffsetLow;
1340 offsetL.ulHi = (OffsetHigh) ? *OffsetHigh : 0;
1341 rc = OdinDosSetFilePtrL(hFile, offsetL, method, &newoffsetL);
1342 if(OffsetHigh) {
1343 *OffsetHigh = newoffsetL.ulHi;
1344 }
1345 newoffset = newoffsetL.ulLo;
1346 }
1347 else
1348#endif
1349 rc = DosSetFilePtr(hFile, OffsetLow, method, &newoffset);
1350
1351 dprintf(("OSLibDosSetFilePointer. method: %08x wanted: %08x moved to %08x",
1352 method, OffsetLow, newoffset));
1353 if(rc)
1354 {
1355 SetLastError(error2WinError(rc));
1356 return -1;
1357 }
1358 SetLastError(ERROR_SUCCESS_W);
1359 return newoffset;
1360}
1361//******************************************************************************
1362//******************************************************************************
1363BOOL OSLibDosSetEndOfFile(DWORD hFile)
1364{
1365 ULONG newFilePos;
1366 LONGLONG FilePosL = {0,0};
1367 LONGLONG newFilePosL;
1368 APIRET rc;
1369
1370 if(f64BitIO) {
1371 rc = OdinDosSetFilePtrL(hFile, FilePosL, FILE_CURRENT, &newFilePosL);
1372 if(rc == 0) {
1373 rc = OdinDosSetFileSizeL(hFile, newFilePosL);
1374 }
1375 }
1376 else {
1377 rc = DosSetFilePtr(hFile, 0, FILE_CURRENT, &newFilePos);
1378 if(rc == 0) {
1379 rc = DosSetFileSize(hFile, newFilePos);
1380 }
1381 }
1382 if(rc) {
1383 SetLastError(error2WinError(rc));
1384 return FALSE;
1385 }
1386 SetLastError(ERROR_SUCCESS_W);
1387 return TRUE;
1388}
1389//******************************************************************************
1390//******************************************************************************
1391BOOL OSLibDosGetFileInformationByHandle(DWORD hFile, BY_HANDLE_FILE_INFORMATION* pInfo)
1392{
1393 APIRET rc;
1394
1395 if(f64BitIO)
1396 {
1397 FILESTATUS4L statusL = { 0 };
1398
1399 rc = DosQueryFileInfo(hFile, FIL_QUERYEASIZEL,
1400 &statusL, sizeof(statusL));
1401 if(rc == NO_ERROR)
1402 {
1403 pInfo->dwFileAttributes = 0;
1404 if(!(statusL.attrFile & NOT_NORMAL))
1405 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_NORMAL_W;
1406 if(statusL.attrFile & FILE_READONLY)
1407 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_READONLY_W;
1408 if(statusL.attrFile & FILE_HIDDEN)
1409 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN_W;
1410 if(statusL.attrFile & FILE_SYSTEM)
1411 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_SYSTEM_W;
1412 if(statusL.attrFile & FILE_DIRECTORY)
1413 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY_W;
1414 if(statusL.attrFile & FILE_ARCHIVED)
1415 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_ARCHIVE_W;
1416
1417 pmDateTimeToFileTime(&statusL.fdateCreation,
1418 &statusL.ftimeCreation,
1419 &pInfo->ftCreationTime);
1420 pmDateTimeToFileTime(&statusL.fdateLastAccess,
1421 &statusL.ftimeLastAccess,
1422 &pInfo->ftLastAccessTime);
1423 pmDateTimeToFileTime(&statusL.fdateLastWrite,
1424 &statusL.ftimeLastWrite,
1425 &pInfo->ftLastWriteTime);
1426
1427 pInfo->nFileSizeHigh = statusL.cbFile.ulHi;
1428 pInfo->nFileSizeLow = statusL.cbFile.ulLo;
1429 pInfo->dwVolumeSerialNumber = 0; //todo
1430 pInfo->nNumberOfLinks = 1;
1431 pInfo->nFileIndexHigh = 0;
1432 pInfo->nFileIndexLow = 0;
1433 }
1434 }
1435 else
1436 {
1437 FILESTATUS4 status = { 0 };
1438
1439 rc = DosQueryFileInfo(hFile, FIL_QUERYEASIZE, &status,
1440 sizeof(status));
1441 if(rc == NO_ERROR)
1442 {
1443 pInfo->dwFileAttributes = 0;
1444 if(!(status.attrFile & NOT_NORMAL))
1445 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_NORMAL_W;
1446 if(status.attrFile & FILE_READONLY)
1447 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_READONLY_W;
1448 if(status.attrFile & FILE_HIDDEN)
1449 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN_W;
1450 if(status.attrFile & FILE_SYSTEM)
1451 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_SYSTEM_W;
1452 if(status.attrFile & FILE_DIRECTORY)
1453 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY_W;
1454 if(status.attrFile & FILE_ARCHIVED)
1455 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_ARCHIVE_W;
1456
1457 pmDateTimeToFileTime(&status.fdateCreation,
1458 &status.ftimeCreation,
1459 &pInfo->ftCreationTime);
1460 pmDateTimeToFileTime(&status.fdateLastAccess,
1461 &status.ftimeLastAccess,
1462 &pInfo->ftLastAccessTime);
1463 pmDateTimeToFileTime(&status.fdateLastWrite,
1464 &status.ftimeLastWrite,
1465 &pInfo->ftLastWriteTime);
1466
1467 pInfo->nFileSizeHigh = 0;
1468 pInfo->nFileSizeLow = status.cbFile;
1469 pInfo->dwVolumeSerialNumber = 0; //todo
1470 pInfo->nNumberOfLinks = 1;
1471 pInfo->nFileIndexHigh = 0;
1472 pInfo->nFileIndexLow = 0;
1473 }
1474 }
1475 if(rc) {
1476 SetLastError(error2WinError(rc));
1477 return FALSE;
1478 }
1479 SetLastError(ERROR_SUCCESS_W);
1480 return TRUE;
1481}
1482//******************************************************************************
1483//******************************************************************************
1484BOOL OSLibDosSetFileTime(DWORD hFile, LPFILETIME pFT1,
1485 LPFILETIME pFT2, LPFILETIME pFT3)
1486{
1487 FILESTATUS3 fileInfo;
1488 APIRET rc;
1489
1490 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &fileInfo, sizeof(fileInfo));
1491
1492 if (rc == NO_ERROR)
1493 {
1494 if (pFT1) pmFileTimeToDateTime(pFT1, &fileInfo.fdateCreation, &fileInfo.ftimeCreation);
1495 if (pFT2) pmFileTimeToDateTime(pFT2, &fileInfo.fdateLastAccess,&fileInfo.ftimeLastAccess);
1496 if (pFT3) pmFileTimeToDateTime(pFT3, &fileInfo.fdateLastWrite, &fileInfo.ftimeLastWrite);
1497
1498 rc = DosSetFileInfo(hFile, FIL_STANDARD, &fileInfo, sizeof(fileInfo));
1499 }
1500
1501 if(rc)
1502 {
1503 SetLastError(error2WinError(rc));
1504 return FALSE;
1505 }
1506 SetLastError(ERROR_SUCCESS_W);
1507 return TRUE;
1508}
1509//******************************************************************************
1510//******************************************************************************
1511BOOL OSLibDosGetFileTime(DWORD hFile, LPFILETIME pFT1,
1512 LPFILETIME pFT2, LPFILETIME pFT3)
1513{
1514 FILESTATUS3 fileInfo;
1515 APIRET rc;
1516
1517 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &fileInfo, sizeof(fileInfo));
1518
1519 if(rc == NO_ERROR)
1520 {
1521 if (pFT1) pmDateTimeToFileTime(&fileInfo.fdateCreation, &fileInfo.ftimeCreation, pFT1);
1522 if (pFT2) pmDateTimeToFileTime(&fileInfo.fdateLastAccess,&fileInfo.ftimeLastAccess,pFT2);
1523 if (pFT3) pmDateTimeToFileTime(&fileInfo.fdateLastWrite, &fileInfo.ftimeLastWrite, pFT3);
1524 }
1525 if(rc)
1526 {
1527 SetLastError(error2WinError(rc));
1528 return FALSE;
1529 }
1530 SetLastError(ERROR_SUCCESS_W);
1531 return TRUE;
1532}
1533//******************************************************************************
1534//******************************************************************************
1535DWORD OSLibDosSetFilePtr2(DWORD hFile, DWORD offset, DWORD method)
1536{
1537 DWORD newoffset;
1538 APIRET rc;
1539
1540
1541 rc = DosSetFilePtr(hFile, offset, method, &newoffset);
1542 if(rc) {
1543 dprintf(("DosSetFilePtr Error rc:%d", rc));
1544 return -1;
1545 }
1546 else return newoffset;
1547}
1548//******************************************************************************
1549//******************************************************************************
1550DWORD OSLibDosDupHandle(DWORD hFile, DWORD *hNew)
1551{
1552 DWORD dwNewHandle = -1, ret;
1553
1554 //Use the stack for storing the new handle; DosDupHandle doesn't like high
1555 //addresses
1556 ret = DosDupHandle(hFile, &dwNewHandle);
1557 *hNew = dwNewHandle;
1558 return ret;
1559}
1560//******************************************************************************
1561//******************************************************************************
1562DWORD OSLibDosSetFHState(DWORD hFile, DWORD dwFlags)
1563{
1564 DWORD ulMode;
1565 APIRET rc;
1566
1567 rc = DosQueryFHState(hFile, &ulMode);
1568 if(rc != NO_ERROR) return error2WinError(rc);
1569
1570 //turn off non-participating bits
1571 ulMode &= 0x7F88;
1572
1573 if(dwFlags & HANDLE_FLAG_INHERIT_W) {
1574 ulMode &= ~OPEN_FLAGS_NOINHERIT;
1575 }
1576 else
1577 ulMode |= OPEN_FLAGS_NOINHERIT;
1578
1579 rc = DosSetFHState(hFile, ulMode);
1580 return error2WinError(rc);
1581}
1582//******************************************************************************
1583//Returns time spent in kernel & user mode in milliseconds
1584//******************************************************************************
1585BOOL OSLibDosQueryProcTimes(DWORD procid, ULONG *kerneltime, ULONG *usertime)
1586{
1587 APIRET rc;
1588 char *buf;
1589 ULONG size;
1590 ULONG nrthreads = 4;
1591
1592tryagain:
1593 size = sizeof(QTOPLEVEL)+sizeof(QGLOBAL)+sizeof(QPROCESS) + nrthreads*sizeof(QTHREAD);
1594 buf = (char *)malloc(size);
1595 rc = DosQuerySysState(0x1, RESERVED, procid, RESERVED, (PCHAR)buf, size);
1596
1597 if(rc) {
1598 free(buf);
1599 if(rc == ERROR_BUFFER_OVERFLOW) {
1600 nrthreads += 4;
1601 goto tryagain;
1602 }
1603 return FALSE;
1604 }
1605 PQTOPLEVEL top = (PQTOPLEVEL)buf;
1606
1607 *kerneltime = 0;
1608 *usertime = 0;
1609 for(int i=0;i<top->procdata->threadcnt;i++) {
1610 *kerneltime += top->procdata->threads[i].systime;
1611 *usertime += top->procdata->threads[i].usertime;
1612 }
1613 free(buf);
1614 return TRUE;
1615}
1616//******************************************************************************
1617//******************************************************************************
1618// TODO: implement SecurityAttributes parameter
1619DWORD OSLibDosCreateNamedPipe(LPCTSTR lpName,
1620 DWORD dwOpenMode,
1621 DWORD dwPipeMode,
1622 DWORD nMaxInstances,
1623 DWORD nOutBufferSize,
1624 DWORD nInBufferSize,
1625 DWORD nDefaultTimeOut,
1626 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
1627{ DWORD dwOS2Mode = NP_NOINHERIT; //default is not inherited by child processes
1628 DWORD dwOS2PipeMode = 0;
1629 LPSTR lpOS2Name;
1630 DWORD hPipe;
1631 DWORD rc, ulAction;
1632
1633 if ((dwOpenMode & PIPE_ACCESS_DUPLEX_W) == PIPE_ACCESS_DUPLEX_W)
1634 dwOS2Mode |= NP_ACCESS_DUPLEX;
1635 else
1636 if (dwOpenMode & PIPE_ACCESS_INBOUND_W)
1637 dwOS2Mode |= NP_ACCESS_INBOUND;
1638 else
1639 if (dwOpenMode & PIPE_ACCESS_OUTBOUND_W)
1640 dwOS2Mode |= NP_ACCESS_OUTBOUND;
1641 // TODO:
1642 // if(dwOpenMode & FILE_FLAG_OVERLAPPED)
1643 // if(dwOpenMode & WRITE_DAC)
1644 // if(dwOpenMode & WRITE_OWNER)
1645 // if(dwOpenMode & ACCESS_SYSTEM_SECURITY)
1646 if(dwOpenMode & FILE_FLAG_WRITE_THROUGH_W)
1647 dwOS2Mode |= NP_WRITEBEHIND; // FIXME: I'm not sure!
1648
1649 if (dwPipeMode & PIPE_WAIT_W)
1650 dwOS2PipeMode |= NP_WAIT;
1651 if (dwPipeMode & PIPE_NOWAIT_W)
1652 dwOS2PipeMode |= NP_NOWAIT;
1653 if (dwPipeMode & PIPE_READMODE_BYTE_W)
1654 dwOS2PipeMode |= NP_READMODE_BYTE;
1655 if (dwPipeMode & PIPE_READMODE_MESSAGE_W)
1656 dwOS2PipeMode |= NP_READMODE_MESSAGE;
1657 if (dwPipeMode & PIPE_TYPE_BYTE_W)
1658 dwOS2PipeMode |= NP_TYPE_BYTE;
1659 if (dwPipeMode & PIPE_TYPE_MESSAGE_W)
1660 dwOS2PipeMode |= NP_TYPE_MESSAGE;
1661
1662 if (nMaxInstances>0xff)
1663 {
1664 SetLastError(ERROR_INVALID_PARAMETER_W); // ERROR_INVALID_PARAMETER
1665 return -1; // INVALID_HANDLE_VALUE
1666 }
1667 dwOS2PipeMode |= nMaxInstances;
1668
1669 if (strstr(lpName,"\\\\."))
1670 {
1671 // If pipe is created on the local machine
1672 // we must delete string \\. because
1673 // in Windows named pipes scheme is a \\.\PIPE\pipename
1674 // but in OS/2 only \PIPE\pipename
1675 lpOS2Name = (LPSTR)lpName + 3;
1676 }
1677 else lpOS2Name = (LPSTR)lpName;
1678
1679 dprintf(("DosCreateNPipe(%s,%x,%x,%x,%x,%x)",lpOS2Name,dwOS2Mode,dwOS2PipeMode,nInBufferSize,nOutBufferSize,nDefaultTimeOut));
1680
1681 //if the windows app tries to open another instance of an existing pipe, then
1682 //we must use DosOpen here. So first try DosOpen, if that fails then we can
1683 //create the named pipe
1684 rc = DosOpen(lpOS2Name, &hPipe, &ulAction, 0, FILE_NORMAL, FILE_OPEN,
1685 ((dwOpenMode & PIPE_ACCESS_INBOUND_W) ? OPEN_ACCESS_READWRITE : OPEN_ACCESS_READONLY) |
1686 OPEN_SHARE_DENYNONE | OPEN_FLAGS_NOINHERIT, NULL);
1687
1688 if(rc == NO_ERROR) {
1689#if 0
1690 //TODO:
1691 if(dwOpenMode & FILE_FLAG_FIRST_PIPE_INSTANCE_W) {
1692 DosClose(hPipe);
1693 SetLastError(ERROR_ALREADY_EXISTS_W);
1694 return -1;
1695 }
1696 else {
1697#endif
1698 dprintf(("Opening of existing named pipe succeeded"));
1699 SetLastError(ERROR_SUCCESS_W);
1700 return hPipe;
1701// }
1702 }
1703
1704 rc=DosCreateNPipe(lpOS2Name,
1705 &hPipe,
1706 dwOS2Mode,
1707 dwOS2PipeMode,
1708 nInBufferSize,
1709 nInBufferSize,
1710 nDefaultTimeOut); // Timeouts must be tested!
1711
1712 dprintf(("DosCreateNPipe rc=%d",rc));
1713 if (rc)
1714 {
1715 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER_W));
1716 return -1; // INVALID_HANDLE_VALUE
1717 }
1718 SetLastError(ERROR_SUCCESS_W);
1719 return hPipe;
1720}
1721//******************************************************************************
1722//******************************************************************************
1723BOOL OSLibSetNamedPipeState(DWORD hNamedPipe, DWORD dwPipeMode)
1724{
1725 ULONG dwOS2PipeMode = 0;
1726 APIRET rc;
1727
1728 if (dwPipeMode & PIPE_WAIT_W)
1729 dwOS2PipeMode |= NP_WAIT;
1730 if (dwPipeMode & PIPE_NOWAIT_W)
1731 dwOS2PipeMode |= NP_NOWAIT;
1732 if (dwPipeMode & PIPE_READMODE_BYTE_W)
1733 dwOS2PipeMode |= NP_READMODE_BYTE;
1734 if (dwPipeMode & PIPE_READMODE_MESSAGE_W)
1735 dwOS2PipeMode |= NP_READMODE_MESSAGE;
1736
1737 rc = DosSetNPHState(hNamedPipe, dwOS2PipeMode);
1738 if(rc) {
1739 SetLastError(error2WinError(rc, ERROR_INVALID_PARAMETER_W));
1740 return FALSE;
1741 }
1742 SetLastError(ERROR_SUCCESS_W);
1743 return TRUE;
1744}
1745//******************************************************************************
1746//******************************************************************************
1747DWORD OSLibDosOpenPipe(LPCTSTR lpName,
1748 DWORD fuAccess,
1749 DWORD fuShare,
1750 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
1751 DWORD fuCreate,
1752 DWORD fuAttrFlags)
1753{
1754 LPSTR lpOS2Name;
1755 ULONG hPipe;
1756 ULONG rc, ulAction;
1757 ULONG openFlag = 0;
1758 ULONG openMode = OPEN_FLAGS_NOINHERIT; //default is not inherited by child processes
1759
1760
1761 switch(fuCreate)
1762 {
1763 case CREATE_NEW_W:
1764 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_FAIL_IF_EXISTS;
1765 break;
1766 case CREATE_ALWAYS_W:
1767 /* kso 2000-11-26: Not sure if OPEN_ACTION_REPLACE_IF_EXISTS is correct here! It is correct according to
1768 * MSDN, but not according to "The Win32 API SuperBible". Anyway I haven't got time to check it out in
1769 * NT now.
1770 * The problem is that OPEN_ACTION_REPLACE_IF_EXISTS requires write access. It failes with
1771 * rc = ERROR_ACCESS_DENIED (5). Quick fix, use OPEN_IF_EXIST if readonly access.
1772 */
1773 if (fuAccess & GENERIC_WRITE_W)
1774 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
1775 else
1776 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
1777 break;
1778 case OPEN_EXISTING_W:
1779 openFlag |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
1780 break;
1781 case OPEN_ALWAYS_W:
1782 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
1783 break;
1784 case TRUNCATE_EXISTING_W:
1785 openFlag |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
1786 break;
1787 }
1788
1789 if(fuAttrFlags & FILE_FLAG_WRITE_THROUGH_W) openMode |= OPEN_FLAGS_WRITE_THROUGH;
1790 if(fuAttrFlags & FILE_FLAG_NO_BUFFERING_W) openMode |= OPEN_FLAGS_NO_CACHE;
1791 if(fuAttrFlags & FILE_FLAG_RANDOM_ACCESS_W) openMode |= OPEN_FLAGS_RANDOM;
1792 if(fuAttrFlags & FILE_FLAG_SEQUENTIAL_SCAN_W) openMode |= OPEN_FLAGS_SEQUENTIAL;
1793 // TODO: FILE_FLAG_BACKUP_SEMANTICS_W
1794 // FILE_FLAG_POSIX_SEMANTICS_W are not supported
1795
1796 //TODO: FILE_SHARE_DELETE
1797 if((fuShare & (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W)) == 0 )
1798 openMode |= OPEN_SHARE_DENYREADWRITE;
1799 else
1800 if((fuShare & (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W)) == (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W))
1801 openMode |= OPEN_SHARE_DENYNONE;
1802 else
1803 if(fuShare & FILE_SHARE_READ_W)
1804 openMode |= OPEN_SHARE_DENYWRITE;
1805 else
1806 if(fuShare & FILE_SHARE_WRITE_W)
1807 openMode |= OPEN_SHARE_DENYREAD;
1808
1809 if(fuAccess == (GENERIC_READ_W | GENERIC_WRITE_W))
1810 openMode |= OPEN_ACCESS_READWRITE;
1811 else
1812 if(fuAccess & GENERIC_READ_W)
1813 openMode |= OPEN_ACCESS_READONLY;
1814 else
1815 if(fuAccess & GENERIC_WRITE_W)
1816 openMode |= OPEN_ACCESS_WRITEONLY;
1817
1818 if (strstr(lpName,"\\\\."))
1819 {
1820 // If pipe is created on the local machine
1821 // we must delete string \\. because
1822 // in Windows named pipes scheme is a \\.\PIPE\pipename
1823 // but in OS/2 only \PIPE\pipename
1824 lpOS2Name = (LPSTR)lpName + 3;
1825 }
1826 else lpOS2Name = (LPSTR)lpName;
1827
1828 rc = DosOpen(lpOS2Name, &hPipe, &ulAction, 0, 0,
1829 openFlag, openMode, NULL);
1830
1831 if(rc == NO_ERROR) {
1832 dprintf(("Opening of existing named pipe succeeded"));
1833 SetLastError(ERROR_SUCCESS_W);
1834 return hPipe;
1835 }
1836
1837 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER_W));
1838 return -1; // INVALID_HANDLE_VALUE
1839}
1840
1841//******************************************************************************
1842//******************************************************************************
1843// TODO: implement lpOverlapped parameter!
1844BOOL OSLibDosConnectNamedPipe(DWORD hNamedPipe, LPOVERLAPPED lpOverlapped)
1845{
1846 DWORD rc;
1847
1848 rc=DosConnectNPipe(hNamedPipe);
1849 dprintf(("DosConnectNPipe rc=%d",rc));
1850
1851 if(rc == NO_ERROR) {
1852 SetLastError(ERROR_SUCCESS_W);
1853 return (TRUE);
1854 }
1855 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1856 return (FALSE);
1857}
1858
1859//******************************************************************************
1860//******************************************************************************
1861BOOL OSLibDosCallNamedPipe( LPCTSTR lpNamedPipeName,
1862 LPVOID lpInBuffer,
1863 DWORD nInBufferSize,
1864 LPVOID lpOutBuffer,
1865 DWORD nOutBufferSize,
1866 LPDWORD lpBytesRead,
1867 DWORD nTimeOut )
1868{
1869 LPSTR lpOS2Name;
1870 DWORD rc;
1871
1872 if (strstr(lpNamedPipeName,"\\\\."))
1873 {
1874 // If pipe is created on the local machine
1875 // we must delete string \\. because
1876 // in Windows named pipes scheme is a \\.\PIPE\pipename
1877 // but in OS/2 only \PIPE\pipename
1878 lpOS2Name = (LPSTR)lpNamedPipeName + 3;
1879 }
1880 else lpOS2Name = (LPSTR)lpNamedPipeName;
1881
1882 rc=DosCallNPipe(lpOS2Name,
1883 lpInBuffer,
1884 nInBufferSize,
1885 lpOutBuffer,
1886 nOutBufferSize,
1887 lpBytesRead,
1888 nTimeOut );
1889
1890
1891 if(rc == NO_ERROR) {
1892 SetLastError(ERROR_SUCCESS_W);
1893 return (TRUE);
1894 }
1895 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1896 return (FALSE);
1897}
1898
1899//******************************************************************************
1900//******************************************************************************
1901BOOL OSLibDosTransactNamedPipe( DWORD hNamedPipe,
1902 LPVOID lpInBuffer,
1903 DWORD nInBufferSize,
1904 LPVOID lpOutBuffer,
1905 DWORD nOutBufferSize,
1906 LPDWORD lpBytesRead,
1907 LPOVERLAPPED lpOverlapped)
1908{
1909 DWORD rc;
1910
1911 rc=DosTransactNPipe(hNamedPipe,
1912 lpOutBuffer,
1913 nOutBufferSize,
1914 lpInBuffer,
1915 nInBufferSize,
1916 lpBytesRead);
1917
1918 dprintf(("DosTransactNPipe returned rc=%d");)
1919 if(rc == NO_ERROR) {
1920 SetLastError(ERROR_SUCCESS_W);
1921 return (TRUE);
1922 }
1923 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1924 return (FALSE);
1925}
1926
1927//******************************************************************************
1928//******************************************************************************
1929BOOL OSLibDosPeekNamedPipe(DWORD hPipe,
1930 LPVOID lpvBuffer,
1931 DWORD cbBuffer,
1932 LPDWORD lpcbRead,
1933 LPDWORD lpcbAvail,
1934 LPDWORD lpcbMessage)
1935{
1936 DWORD rc;
1937 AVAILDATA availData ={0};
1938 ULONG ulState, ulRead, ulMessage;
1939 char buffer;
1940
1941 if(lpcbRead == NULL) {
1942 lpcbRead = &ulRead;
1943 }
1944 if(lpcbMessage == NULL) {
1945 lpcbMessage = &ulMessage;
1946 }
1947 if(lpvBuffer == NULL) {
1948 lpvBuffer = &buffer;
1949 cbBuffer = 0;
1950 }
1951
1952 rc = DosPeekNPipe(hPipe,lpvBuffer,cbBuffer,lpcbRead,&availData,&ulState);
1953
1954 dprintf(("DosPeekNPipe returned rc=%d",rc));
1955
1956 //OS/2 doesn't support DosPeekNPipe for unnamed pipes; win32 does
1957 if (rc == 1) {
1958 dprintf(("WARNING: Pretend broken pipe for PeekNamedPipe with unnamed pipe handle"));
1959 SetLastError(ERROR_BROKEN_PIPE_W);
1960 return FALSE;
1961 }
1962 if (rc == NO_ERROR)
1963 {
1964 if(lpcbAvail) {
1965 *lpcbAvail = availData.cbpipe;
1966 }
1967 if(lpcbMessage) {
1968 *lpcbMessage = availData.cbmessage;
1969 }
1970 SetLastError(ERROR_SUCCESS_W);
1971 return (TRUE);
1972 }
1973 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1974 return (FALSE);
1975}
1976//******************************************************************************
1977//******************************************************************************
1978BOOL OSLibDosDisconnectNamedPipe(DWORD hPipe)
1979{
1980 DWORD rc;
1981
1982 rc=DosDisConnectNPipe(hPipe);
1983
1984 dprintf(("DosDisConnectNPipe returned rc=%d",rc));
1985
1986 if(rc == NO_ERROR) {
1987 SetLastError(ERROR_SUCCESS_W);
1988 return (TRUE);
1989 }
1990 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1991 return (FALSE);
1992}
1993//******************************************************************************
1994//******************************************************************************
1995BOOL OSLibDosWaitNamedPipe(LPCSTR lpszNamedPipeName,
1996 DWORD dwTimeout)
1997{
1998 LPSTR lpOS2Name;
1999 DWORD rc;
2000
2001 if (strstr(lpszNamedPipeName,"\\\\."))
2002 {
2003 // If pipe is created on the local machine
2004 // we must delete string \\. because
2005 // in Windows named pipes scheme is a \\.\PIPE\pipename
2006 // but in OS/2 only \PIPE\pipename
2007 lpOS2Name = (LPSTR)lpszNamedPipeName + 3;
2008 }
2009 else lpOS2Name = (LPSTR)lpszNamedPipeName;
2010
2011 rc=DosWaitNPipe(lpOS2Name,dwTimeout);
2012
2013 dprintf(("DosWaitNPipe returned rc=%d",rc));
2014
2015 if(rc == NO_ERROR) {
2016 SetLastError(ERROR_SUCCESS_W);
2017 return (TRUE);
2018 }
2019 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
2020
2021 return (FALSE);
2022}
2023//******************************************************************************
2024//******************************************************************************
2025BOOL isRoot(CHAR* name)
2026{
2027 if (name[1] == ':')
2028 {
2029 //local name (x:\)
2030 return (name[2] == 0) || !strchr(&name[3],'\\');
2031 } else if (name[0] == '\\')
2032 {
2033 //UNC name (\\resource\drive\)
2034 CHAR *drive,*dir;
2035
2036 drive = strchr(&name[2],'\\');
2037 if (!drive) return FALSE;
2038 dir = strchr(&drive[1],'\\');
2039 if (!dir) return TRUE;
2040 return !strchr(&dir[1],'\\');
2041 } else return FALSE; //unknown
2042}
2043//******************************************************************************
2044//******************************************************************************
2045inline CHAR system2DOSCharacter(CHAR ch)
2046{
2047 switch(ch)
2048 {
2049 case ' ':
2050 case '.':
2051 case '~':
2052 return '_';
2053
2054 default:
2055 return toupper(ch);
2056 }
2057}
2058
2059// TODO: not finished nor correct!!!!
2060VOID long2ShortName(CHAR* longName, CHAR* shortName)
2061{
2062 // check for uplink / root: "." and ".."
2063 if (longName[0] == '.')
2064 {
2065 // if ((strcmp(longName,".") == 0) || (strcmp(longName,"..") == 0))
2066 if (longName[1] == 0) // "."
2067 {
2068 shortName[0] = '.';
2069 shortName[1] = 0;
2070 return;
2071 }
2072
2073 if (longName[1] == '.' && longName[2] == 0) // ".."
2074 {
2075 shortName[0] = '.';
2076 shortName[1] = '.';
2077 shortName[2] = 0;
2078 return;
2079 }
2080 }
2081 else
2082 // check for empty name
2083 if(longName[0] == 0)
2084 {
2085 shortName[0] = 0;
2086 return;
2087 }
2088
2089 INT x;
2090 CHAR *source = longName;
2091
2092 // Test if longName is 8:3 compliant and simply copy
2093 // the filename.
2094 BOOL flag83 = TRUE;
2095
2096 // verify forbidden characters
2097 for (x = 0;
2098 (x < 8) &&
2099 (flag83 == TRUE);
2100 x++)
2101 {
2102 switch (*source)
2103 {
2104 case '.': // a period will cause the loop to abort!
2105 x=1000;
2106 break;
2107
2108 case '/': case '?':
2109 case '*': case ':':
2110 case '\\': case '"':
2111 case ' ':
2112 flag83 = FALSE;
2113 break;
2114 default:
2115 source++;
2116 break;
2117 }
2118 }
2119
2120 // verify we're on a period now
2121 if (flag83 == TRUE)
2122 if (*source != '.')
2123 flag83 = FALSE;
2124 else source++;
2125
2126 // verify extension
2127 if (flag83 == TRUE)
2128 for (INT y = 0;
2129 (y < 3) && (flag83 == TRUE);
2130 y++)
2131 {
2132 switch (*source)
2133 {
2134 case '/': case '?':
2135 case '*': case ':':
2136 case '\\': case '"':
2137 case ' ': case '.':
2138 flag83 = FALSE;
2139 break;
2140 }
2141 source++;
2142 }
2143
2144 // verify we're at the end of the string now
2145 if (flag83 == TRUE)
2146 if (*source != 0)
2147 flag83 = FALSE;
2148
2149 // OK, done
2150 if (flag83 == TRUE)
2151 {
2152 // we might not alter any character here, since
2153 // an app opening a specific file with an 8:3 "alias",
2154 // would surely fail.
2155 strcpy(shortName, longName);
2156
2157 return; // Done
2158 }
2159
2160
2161 // @@@PH
2162 shortName[0] = 0; // this function is disabled anyway ...
2163 return;
2164
2165 CHAR *dest = shortName;
2166 CHAR *ext = strrchr(longName,'.');
2167
2168 //CB: quick and dirty, real FILE~12.EXT is too slow
2169 //PH: We'd have to count the number of non-8:3-compliant files
2170 // within a directory. Or simpler: the number of files within
2171 // the current directory.
2172
2173 //8 character file name
2174 for (x = 0;x < 8;x++)
2175 {
2176 if ((source == ext) || (source[0] == 0)) break;
2177 dest[0] = system2DOSCharacter(source[0]);
2178 source++;
2179 dest++;
2180 }
2181
2182 if (source[0] == 0)
2183 {
2184 dest[0] = 0;
2185 return;
2186 }
2187
2188 if (source != ext)
2189 {
2190 //longName > 8 characters, insert ~1
2191 shortName[6] = '~';
2192 shortName[7] = '1';
2193 }
2194
2195 if (ext)
2196 {
2197 //add extension, 3 characters
2198 dest[0] = ext[0];
2199 dest++;
2200 ext++;
2201 for (x = 0;x < 3;x++)
2202 {
2203 if (ext[0] == 0) break;
2204 dest[0] = system2DOSCharacter(ext[0]);
2205 ext++;
2206 dest++;
2207 }
2208 }
2209 dest[0] = 0;
2210}
2211//******************************************************************************
2212//******************************************************************************
2213VOID translateFileResults(FILESTATUS3 *pResult,LPWIN32_FIND_DATAA pFind,CHAR* achName)
2214{
2215 CHAR* name;
2216
2217 pFind->dwReserved0 = pFind->dwReserved1 = 0;
2218 pFind->dwFileAttributes = pm2WinFileAttributes(pResult->attrFile);
2219
2220 pmDateTimeToFileTime(&pResult->fdateCreation,&pResult->ftimeCreation,&pFind->ftCreationTime);
2221 pmDateTimeToFileTime(&pResult->fdateLastAccess,&pResult->ftimeLastAccess,&pFind->ftLastAccessTime);
2222 pmDateTimeToFileTime(&pResult->fdateLastWrite,&pResult->ftimeLastWrite,&pFind->ftLastWriteTime);
2223
2224 pFind->nFileSizeHigh = 0; //CB: fixme
2225 pFind->nFileSizeLow = pResult->cbFile;
2226 name = strrchr(achName,'\\');
2227 if (name)
2228 {
2229 name++;
2230// strcpy(pFind->cFileName,name);
2231 OemToCharA( name, pFind->cFileName );
2232 }
2233 else
2234 pFind->cFileName[0] = 0;
2235
2236 long2ShortName(pFind->cFileName,pFind->cAlternateFileName);
2237}
2238
2239
2240VOID translateFindResults(FILEFINDBUF3 *pResult,LPWIN32_FIND_DATAA pFind)
2241{
2242 pFind->dwFileAttributes = pm2WinFileAttributes(pResult->attrFile);
2243 pFind->dwReserved0 = pFind->dwReserved1 = 0;
2244
2245 pmDateTimeToFileTime(&pResult->fdateCreation,&pResult->ftimeCreation,&pFind->ftCreationTime);
2246 pmDateTimeToFileTime(&pResult->fdateLastAccess,&pResult->ftimeLastAccess,&pFind->ftLastAccessTime);
2247 pmDateTimeToFileTime(&pResult->fdateLastWrite,&pResult->ftimeLastWrite,&pFind->ftLastWriteTime);
2248
2249 pFind->nFileSizeHigh = 0; //CB: fixme
2250 pFind->nFileSizeLow = pResult->cbFile;
2251// strcpy(pFind->cFileName,pResult->achName);
2252 OemToCharA( pResult->achName, pFind->cFileName );
2253 long2ShortName(pFind->cFileName,pFind->cAlternateFileName);
2254}
2255//******************************************************************************
2256//******************************************************************************
2257DWORD OSLibDosFindFirst(LPCSTR lpFileName,WIN32_FIND_DATAA* lpFindFileData)
2258{
2259 HDIR hDir = -1;
2260 ULONG attrs;
2261 FILEFINDBUF3 result;
2262 ULONG searchCount = 1;
2263
2264 attrs = FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED;
2265 result.achName[0] = 0;
2266
2267 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS_W);
2268 char lOemFileName[260];
2269
2270 CharToOemA(ODINHelperStripUNC((char*)lpFileName), lOemFileName);
2271
2272 APIRET rc = DosFindFirst((PSZ)lOemFileName,&hDir,attrs,&result,sizeof(result),&searchCount,FIL_STANDARD);
2273
2274 //check root: skip "." and ".." (HPFS, not on FAT)
2275 //check in OSLibDosFindNext not necessary: "." and ".." are the first two entries
2276 if ((rc == 0) && isRoot((LPSTR)ODINHelperStripUNC((char*)lpFileName)))
2277 {
2278 while ((strcmp(result.achName,".") == 0) ||
2279 (strcmp(result.achName,"..") == 0))
2280 {
2281 result.achName[0] = 0;
2282 searchCount = 1;
2283 APIRET rc = DosFindNext(hDir,&result,sizeof(result),&searchCount);
2284 if (rc)
2285 {
2286 DosFindClose(hDir);
2287 SetLastError(error2WinError(rc));
2288
2289 SetErrorMode(oldmode);
2290 return INVALID_HANDLE_VALUE_W;
2291 }
2292 }
2293 }
2294
2295 // enable i/o kernel exceptions again
2296 SetErrorMode(oldmode);
2297
2298 if(rc)
2299 {
2300 DosFindClose(hDir);
2301
2302 //Windows returns ERROR_FILE_NOT_FOUND if the file/directory is not present
2303 if(rc == ERROR_NO_MORE_FILES || rc == ERROR_PATH_NOT_FOUND) {
2304 SetLastError(ERROR_FILE_NOT_FOUND_W);
2305 }
2306 else SetLastError(error2WinError(rc));
2307 return INVALID_HANDLE_VALUE_W;
2308 }
2309 translateFindResults(&result,lpFindFileData);
2310 SetLastError(ERROR_SUCCESS_W);
2311 return hDir;
2312}
2313//******************************************************************************
2314// NOTE: returns "." and ".." in root
2315//******************************************************************************
2316DWORD OSLibDosFindFirstMulti(LPCSTR lpFileName,WIN32_FIND_DATAA *lpFindFileData,DWORD *count)
2317{
2318 HDIR hDir = -1;
2319 ULONG attrs;
2320 FILEFINDBUF3 *result,*data;
2321 ULONG searchCount = *count;
2322
2323 attrs = FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED;
2324 result = (FILEFINDBUF3*)malloc(searchCount*sizeof(FILEFINDBUF3));
2325
2326 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS_W);
2327 char lOemFileName[260];
2328
2329 CharToOemA(ODINHelperStripUNC((char*)lpFileName), lOemFileName);
2330 APIRET rc = DosFindFirst((PSZ)lOemFileName,&hDir,attrs,result,searchCount*sizeof(FILEFINDBUF3),&searchCount,FIL_STANDARD);
2331 SetErrorMode(oldmode);
2332 if (rc)
2333 {
2334 free(result);
2335 *count = 0;
2336 SetLastError(error2WinError(rc));
2337
2338 return INVALID_HANDLE_VALUE_W;
2339 }
2340
2341 data = result;
2342 for (int x = 0;x < searchCount;x++)
2343 {
2344 translateFindResults(data,&lpFindFileData[x]);
2345 data = (FILEFINDBUF3*)(((DWORD)data)+data->oNextEntryOffset);
2346 }
2347 free(result);
2348 *count = searchCount;
2349
2350 SetLastError(ERROR_SUCCESS_W);
2351 return hDir;
2352}
2353//******************************************************************************
2354//******************************************************************************
2355BOOL OSLibDosFindNext(DWORD hFindFile,WIN32_FIND_DATAA *lpFindFileData)
2356{
2357 FILEFINDBUF3 result;
2358 ULONG searchCount = 1;
2359
2360 APIRET rc = DosFindNext((HDIR)hFindFile,&result,sizeof(result),&searchCount);
2361 if (rc)
2362 {
2363 SetLastError(error2WinError(rc));
2364
2365 return FALSE;
2366 }
2367
2368 translateFindResults(&result,lpFindFileData);
2369 SetLastError(ERROR_SUCCESS_W);
2370 return TRUE;
2371}
2372//******************************************************************************
2373//******************************************************************************
2374BOOL OSLibDosFindNextMulti(DWORD hFindFile,WIN32_FIND_DATAA *lpFindFileData,DWORD *count)
2375{
2376 FILEFINDBUF3 *result,*data;
2377 ULONG searchCount = *count;
2378
2379 result = (FILEFINDBUF3*)malloc(searchCount*sizeof(FILEFINDBUF3));
2380 APIRET rc = DosFindNext((HDIR)hFindFile,result,searchCount*sizeof(FILEFINDBUF3),&searchCount);
2381 if (rc)
2382 {
2383 free(result);
2384 *count = 0;
2385 SetLastError(error2WinError(rc));
2386
2387 return FALSE;
2388 }
2389
2390 data = result;
2391 for (int x = 0;x < searchCount;x++)
2392 {
2393 translateFindResults(data,&lpFindFileData[x]);
2394 data = (FILEFINDBUF3*)(((DWORD)data)+data->oNextEntryOffset);
2395 }
2396 free(result);
2397 *count = searchCount;
2398
2399 SetLastError(ERROR_SUCCESS_W);
2400 return TRUE;
2401}
2402//******************************************************************************
2403//******************************************************************************
2404BOOL OSLibDosFindClose(DWORD hFindFile)
2405{
2406 APIRET rc = DosFindClose((HDIR)hFindFile);
2407 if (rc)
2408 {
2409 SetLastError(error2WinError(rc));
2410 return FALSE;
2411 }
2412
2413 SetLastError(ERROR_SUCCESS_W);
2414 return TRUE;
2415}
2416//******************************************************************************
2417//******************************************************************************
2418DWORD OSLibGetFileAttributes(LPSTR lpFileName)
2419{
2420 FILESTATUS3 statusBuf;
2421 char lOemFileName[CCHMAXPATH];
2422 char *lpszBackslash, *lpszColon;
2423 APIRET rc;
2424
2425//testestest
2426 if(strlen(lpFileName) > CCHMAXPATH) DebugInt3();
2427//testestset
2428
2429 //Convert file name from Windows to OS/2 codepage
2430 CharToOemA(ODINHelperStripUNC(lpFileName), lOemFileName);
2431 lpszBackslash = CharPrevA(lOemFileName, lOemFileName + strlen(lOemFileName));
2432 if(lpszBackslash)
2433 {
2434 if(*lpszBackslash == '\\')
2435 {
2436 lpszColon = CharPrevA(lOemFileName, lpszBackslash);
2437 if(lpszColon && *lpszColon != ':')
2438 {//only rootdir is allowed to have terminating backslash
2439 *lpszBackslash = 0;
2440 }
2441 }
2442 else
2443 if(*lpszBackslash == ':')
2444 {//root dir must end with backslash
2445 strcat(lOemFileName, "\\");
2446 }
2447 }
2448
2449 rc = DosQueryPathInfo(lOemFileName, FIL_STANDARD, &statusBuf, sizeof(statusBuf));
2450 if(rc == ERROR_TOO_MANY_OPEN_FILES)
2451 {
2452 LONG reqCount = 2;
2453 ULONG maxFiles;
2454
2455 if(DosSetRelMaxFH(&reqCount, &maxFiles) == NO_ERROR)
2456 rc = DosQueryPathInfo(lOemFileName, FIL_STANDARD, &statusBuf, sizeof(statusBuf));
2457 }
2458
2459 if(rc == NO_ERROR)
2460 {
2461 DWORD status = 0;
2462 if(!(statusBuf.attrFile & NOT_NORMAL))
2463 status |= FILE_ATTRIBUTE_NORMAL_W;
2464 if(statusBuf.attrFile & FILE_READONLY)
2465 status |= FILE_ATTRIBUTE_READONLY_W;
2466 if(statusBuf.attrFile & FILE_HIDDEN)
2467 status |= FILE_ATTRIBUTE_HIDDEN_W;
2468 if(statusBuf.attrFile & FILE_SYSTEM)
2469 status |= FILE_ATTRIBUTE_SYSTEM_W;
2470 if(statusBuf.attrFile & FILE_DIRECTORY)
2471 status |= FILE_ATTRIBUTE_DIRECTORY_W;
2472 if(statusBuf.attrFile & FILE_ARCHIVED)
2473 status |= FILE_ATTRIBUTE_ARCHIVE_W;
2474
2475 SetLastError(ERROR_SUCCESS_W);
2476 return status;
2477 }
2478 SetLastError(error2WinError(rc));
2479 return -1;
2480}
2481//******************************************************************************
2482#define FSATTACH_SIZE 256
2483//******************************************************************************
2484DWORD OSLibDosQueryVolumeFS(int drive, LPSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize)
2485{
2486 PFSQBUFFER2 fsinfo = (PFSQBUFFER2) alloca(FSATTACH_SIZE);
2487 ULONG cb = FSATTACH_SIZE;
2488 char drv[3] = "A:";
2489 char *fsname;
2490 APIRET rc;
2491
2492 if(lpFileSystemNameBuffer == NULL) {
2493 DebugInt3();
2494 return ERROR_INVALID_PARAMETER_W;
2495 }
2496 drv[0] = (char)('A' + drive - 1);
2497
2498 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS_W);
2499 rc = DosQueryFSAttach(drv, 1, FSAIL_QUERYNAME, fsinfo, &cb);
2500 SetErrorMode(oldmode);
2501
2502 switch(rc) {
2503 case ERROR_INVALID_DRIVE:
2504 return ERROR_INVALID_DRIVE_W;
2505 case ERROR_NO_VOLUME_LABEL:
2506 return ERROR_NO_VOLUME_LABEL_W;
2507 case NO_ERROR:
2508 break;
2509 default:
2510 return ERROR_NOT_ENOUGH_MEMORY; //whatever
2511 }
2512
2513 fsname = (char *)&fsinfo->szName[0] + fsinfo->cbName + 1;
2514
2515 /* @@@PH 2000/08/10 CMD.EXE querys with nFileSystemNameSize == 0
2516 * however does NOT expect to receive an error.
2517 */
2518 strncpy(lpFileSystemNameBuffer,
2519 fsname,
2520 nFileSystemNameSize);
2521 /*
2522 if(strlen(fsname) < nFileSystemNameSize) {
2523 strcpy(lpFileSystemNameBuffer, fsname);
2524 }
2525 else return ERROR_BUFFER_OVERFLOW_W;
2526 */
2527 return ERROR_SUCCESS_W;
2528}
2529//******************************************************************************
2530typedef struct _FSINFOBUF
2531{
2532 ULONG ulVolser; /* Volume serial number */
2533 VOLUMELABEL vol; /* Volume lable */
2534} FSINFOBUF;
2535//******************************************************************************
2536DWORD OSLibDosQueryVolumeSerialAndName(int drive, LPDWORD lpVolumeSerialNumber,
2537 LPSTR lpVolumeNameBuffer, DWORD nVolumeNameSize)
2538{
2539 FSINFOBUF fsi;
2540 APIRET rc;
2541
2542 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS_W);
2543 rc = DosQueryFSInfo(drive, FSIL_VOLSER, &fsi, sizeof(fsi));
2544 SetErrorMode(oldmode);
2545
2546 switch(rc) {
2547 case ERROR_INVALID_DRIVE:
2548 return ERROR_INVALID_DRIVE_W;
2549 case ERROR_NO_VOLUME_LABEL:
2550 return ERROR_NO_VOLUME_LABEL_W;
2551 case NO_ERROR:
2552 break;
2553 default:
2554 return ERROR_NOT_ENOUGH_MEMORY; //whatever
2555 }
2556
2557 if(lpVolumeSerialNumber) {
2558 *lpVolumeSerialNumber = fsi.ulVolser;
2559 }
2560 if(lpVolumeNameBuffer)
2561 {
2562 if(nVolumeNameSize > fsi.vol.cch) {
2563 strcpy(lpVolumeNameBuffer, (PCHAR)fsi.vol.szVolLabel);
2564 }
2565 else return ERROR_BUFFER_OVERFLOW_W;
2566 }
2567
2568 return ERROR_SUCCESS_W;
2569}
2570//******************************************************************************
2571//******************************************************************************
2572BOOL OSLibGetDiskFreeSpace(LPSTR lpRootPathName, LPDWORD lpSectorsPerCluster,
2573 LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters,
2574 LPDWORD lpTotalNumberOfClusters)
2575{
2576 ULONG diskNum;
2577 FSALLOCATE fsAlloc;
2578 APIRET rc;
2579
2580 if(lpRootPathName == 0)
2581 diskNum = 0;
2582 else
2583 if('A' <= *lpRootPathName && *lpRootPathName <= 'Z' )
2584 diskNum = *lpRootPathName - 'A' + 1;
2585 else
2586 if('a' <= *lpRootPathName && *lpRootPathName <= 'z' )
2587 diskNum = *lpRootPathName - 'a' + 1;
2588 else
2589 diskNum = 0;
2590
2591 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS_W);
2592 rc = DosQueryFSInfo(diskNum, FSIL_ALLOC, &fsAlloc, sizeof(fsAlloc));
2593 SetErrorMode(oldmode);
2594
2595 if(rc == 0)
2596 {
2597 *lpSectorsPerCluster = fsAlloc.cSectorUnit;
2598 *lpBytesPerSector = fsAlloc.cbSector;
2599 *lpNumberOfFreeClusters = fsAlloc.cUnitAvail;
2600 *lpTotalNumberOfClusters = fsAlloc.cUnit;
2601 SetLastError(ERROR_SUCCESS_W);
2602 return TRUE;
2603 }
2604 SetLastError(error2WinError(rc));
2605 return FALSE;
2606}
2607//******************************************************************************
2608//******************************************************************************
2609BOOL OSLibDosGetDiskGeometry(HANDLE hDisk, DWORD cDisk, PVOID pdiskgeom)
2610{
2611 PDISK_GEOMETRY pGeom = (PDISK_GEOMETRY)pdiskgeom;
2612 BYTE param[2] = {0, 0};
2613 ULONG parsize = 2;
2614 BIOSPARAMETERBLOCK bpb;
2615 ULONG datasize = sizeof(bpb);
2616 APIRET rc;
2617
2618 dprintf(("OSLibDosGetDiskGeometry %x %d %x", hDisk, cDisk, pdiskgeom));
2619 param[1] = cDisk - 'A';
2620 rc = DosDevIOCtl((hDisk) ? hDisk : -1, IOCTL_DISK, DSK_GETDEVICEPARAMS, param, 2, &parsize, &bpb, sizeof(bpb), &datasize);
2621 if(rc == 0)
2622 {
2623 pGeom->SectorsPerTrack = bpb.usSectorsPerTrack;
2624 pGeom->BytesPerSector = bpb.usBytesPerSector;
2625 pGeom->TracksPerCylinder = 80; //TODO:!!!!!
2626 pGeom->Cylinders.u.LowPart = bpb.cCylinders;
2627 pGeom->Cylinders.u.HighPart = 0;
2628 switch(bpb.bDeviceType) {
2629 case DEVTYPE_48TPI:
2630 pGeom->MediaType = F5_360_512; //?????
2631 break;
2632 case DEVTYPE_96TPI:
2633 pGeom->MediaType = F5_1Pt2_512; //?????
2634 break;
2635 case DEVTYPE_35:
2636 pGeom->MediaType = F3_720_512;
2637 break;
2638 case DEVTYPE_8SD:
2639 case DEVTYPE_8DD:
2640 pGeom->MediaType = RemovableMedia;
2641 break;
2642 case DEVTYPE_FIXED:
2643 pGeom->MediaType = FixedMedia;
2644 break;
2645 case DEVTYPE_TAPE:
2646 pGeom->MediaType = RemovableMedia;
2647 break;
2648 case DEVTYPE_UNKNOWN: //others, include 1.44 3.5 inch disk drive
2649 pGeom->MediaType = F3_1Pt44_512;
2650 break;
2651 case 8: //RW optical disk
2652 pGeom->MediaType = RemovableMedia;
2653 break;
2654 case 9: //2.88 3.5 inch disk
2655 pGeom->MediaType = F3_2Pt88_512;
2656 break;
2657 }
2658 SetLastError(ERROR_SUCCESS_W);
2659 return TRUE;
2660 }
2661 dprintf(("OSLibDosGetDiskGeometry: error %d -> %d", rc, error2WinError(rc)));
2662 SetLastError(error2WinError(rc));
2663 return FALSE;
2664}
2665//******************************************************************************
2666
2667#define CDType 0x8000
2668#define FloppyType 0x4000
2669#define LanType 0x2000
2670#define LogicalType 0x1000
2671#define VDISKType 0x0800
2672#define OpticalType 0x0400
2673#define NonRemovable 0x01
2674
2675#define FirstDrive 0
2676#define B_Drive_0_Based 1
2677#define Base_1_offset 1
2678#define Binary_to_Printable 0x41
2679#define LastDrive 26
2680#define OpticalSectorsPerCluster 4
2681
2682#define DisketteCylinders 80
2683
2684
2685
2686/**
2687 * Determin the type of a specific drive or the current drive.
2688 *
2689 * @returns DRIVE_UNKNOWN
2690 * DRIVE_NO_ROOT_DIR
2691 * DRIVE_CANNOTDETERMINE
2692 * DRIVE_DOESNOTEXIST
2693 * DRIVE_REMOVABLE
2694 * DRIVE_FIXED
2695 * DRIVE_REMOTE
2696 * DRIVE_CDROM
2697 * DRIVE_RAMDISK
2698 *
2699 * @param ulDrive Index of the drive which type we query.
2700 *
2701 * @status completely implemented and tested
2702 * @author Vitali Pelenyov <sunlover@anduin.net>
2703 * @author bird
2704 */
2705ULONG OSLibGetDriveType(ULONG ulDrive)
2706{
2707 ULONG cbParm;
2708 ULONG cbData;
2709 ULONG ulDriveNum = 0;
2710 ULONG ulDriveMap = 0;
2711 APIRET rc;
2712 ULONG ulDriveType;
2713
2714
2715 /*
2716 * Check if drive is present in the logical drive mask,
2717 */
2718 if ( DosQueryCurrentDisk(&ulDriveNum, &ulDriveMap)
2719 || !(ulDriveMap & (1 << ulDrive))
2720 )
2721 return DRIVE_DOESNOTEXIST_W;
2722
2723
2724 /*
2725 * Optimize floppy queries for A: and B:.
2726 * (These aren't currently a subject of change.)
2727 */
2728 static ULONG ulFloppyMask = 0;
2729 if (ulFloppyMask & (1 << ulDrive))
2730 return DRIVE_REMOVABLE_W;
2731
2732 /*
2733 * Optimize for CDROM requests.
2734 * (These aren't currently a subject of change.)
2735 */
2736 static ULONG ulCDROMMask = 0;
2737 if (ulCDROMMask & (1 << ulDrive))
2738 return DRIVE_CDROM_W;
2739
2740 /*
2741 * Check for CD drives
2742 * We don't have to this everytime. I mean, the os2cdrom.dmd is
2743 * exactly very dynamic when it comes to this info.
2744 */
2745 if (cdDrvLtr.drive_count == 0xffff)
2746 {
2747 HFILE hCDRom2;
2748 ULONG ulAction = 0;
2749
2750 if (DosOpen("\\DEV\\CD-ROM2$", &hCDRom2, &ulAction, 0,
2751 FILE_NORMAL, OPEN_ACTION_OPEN_IF_EXISTS,
2752 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY | OPEN_FLAGS_NOINHERIT, NULL)
2753 == NO_ERROR)
2754 {
2755 cbData = sizeof(cdDrvLtr);
2756 rc = DosDevIOCtl(hCDRom2,
2757 IOC_CDROM_2,
2758 IOCD_RETURN_DRIVE_LETTER,
2759 NULL, 0, NULL,
2760 (PVOID)&cdDrvLtr, sizeof(cdDrvLtr), &cbData);
2761 DosClose(hCDRom2);
2762 }
2763 else
2764 cdDrvLtr.drive_count = 0;
2765 }
2766
2767
2768 /*
2769 * Is the drive present?? Lets the the BPB to check this.
2770 * this should be a pretty speedy call if I'm not much mistaken.
2771 */
2772 BIOSPARAMETERBLOCK bpb = {0};
2773 DSKREQ DskReq;
2774 DskReq.Infotype = 0;
2775 DskReq.DriveUnit = (UCHAR)ulDrive;
2776 cbParm = sizeof(DskReq);
2777 cbData = sizeof(bpb);
2778 if (DosDevIOCtl(-1, IOCTL_DISK, DSK_GETDEVICEPARAMS,
2779 (PVOID)&DskReq, sizeof(DskReq), &cbParm,
2780 (PVOID)&bpb, sizeof(BIOSPARAMETERBLOCK), &cbData)
2781 == NO_ERROR)
2782 {
2783 if (bpb.bDeviceType == 0 && bpb.fsDeviceAttr == 0)
2784 bpb.fsDeviceAttr = LanType; // fix for LAN type drives
2785 }
2786 else
2787 bpb.fsDeviceAttr = LanType; //could be a LAN drive - could it??
2788
2789
2790 /*
2791 * This is a CDROM/DVD drive
2792 *
2793 * Fix: When the cdrom is not last drive letter that
2794 * sometimes reports wrong index, have to check
2795 * that device type can be a CDROM one.
2796 */
2797 if ( cdDrvLtr.drive_count > 0
2798 && (bpb.bDeviceType == DEVTYPE_UNKNOWN || bpb.bDeviceType == DEVTYPE_OPTICAL) // Other or RW optical
2799 && ulDrive >= cdDrvLtr.first_drive_number
2800 && ulDrive < cdDrvLtr.first_drive_number + cdDrvLtr.drive_count
2801 )
2802 bpb.fsDeviceAttr |= CDType;
2803
2804
2805 if (bpb.bDeviceType || bpb.fsDeviceAttr == LanType)
2806 {
2807 if ((bpb.fsDeviceAttr & (CDType | NonRemovable)) == 0)
2808 { // if the device is removable and NOT a CD
2809 CHAR szDevName[4] = "A:";
2810 PFSQBUFFER2 pfsqbuf2;
2811
2812 szDevName[0] += ulDrive;
2813 cbData = sizeof(PFSQBUFFER2) + 3 * CCHMAXPATH;
2814 pfsqbuf2 = (PFSQBUFFER2)malloc(cbData);
2815 DosError(FERR_DISABLEEXCEPTION | FERR_DISABLEHARDERR); // disable error popups
2816 rc = DosQueryFSAttach(&szDevName[0], 0L, FSAIL_QUERYNAME, pfsqbuf2, &cbData);
2817 if (rc == NO_ERROR)
2818 {
2819 if (pfsqbuf2->iType == FSAT_REMOTEDRV)
2820 bpb.fsDeviceAttr |= LanType;
2821 else if (pfsqbuf2->iType == FSAT_LOCALDRV)
2822 {
2823 PSZ pszFSName = (PSZ)pfsqbuf2->szName + pfsqbuf2->cbName + 1;
2824 if (!strcmp(pszFSName, "FAT"))
2825 {
2826 // device is a removable FAT drive, so it MUST be diskette
2827 // as Optical has another name as does LAN and SRVIFS
2828 if (bpb.bSectorsPerCluster != OpticalSectorsPerCluster)
2829 bpb.fsDeviceAttr |= FloppyType;
2830 else
2831 bpb.fsDeviceAttr |= OpticalType;
2832 }
2833 /*
2834 * CDROM detection fix
2835 */
2836 else
2837 {
2838 // device is removable non-FAT, maybe it is CD?
2839 if ( bpb.bDeviceType == DEVTYPE_UNKNOWN
2840 && bpb.bMedia == 5
2841 && bpb.usBytesPerSector > 512
2842 )
2843 bpb.fsDeviceAttr |= CDType;
2844 }
2845 // CDROM detection fix
2846 }
2847 }
2848 else // must be no media or audio only (for CDs at least)
2849 {
2850 if (bpb.cCylinders <= DisketteCylinders) // floppies will always be 80
2851 {
2852 // or less cylinders
2853 if (bpb.bSectorsPerCluster != OpticalSectorsPerCluster)
2854 bpb.fsDeviceAttr |= FloppyType;
2855 else
2856 bpb.fsDeviceAttr |= OpticalType;
2857 }
2858 }
2859
2860 //Enable error popups again
2861 DosError(FERR_ENABLEEXCEPTION | FERR_ENABLEHARDERR);
2862
2863 free(pfsqbuf2);
2864 }
2865 else
2866 {// non removable or CD type. maybe RAM disk
2867 if (!(bpb.fsDeviceAttr & CDType)) // if NOT CD
2868 {
2869 if (bpb.cFATs == 1) // is there only one FAT?
2870 bpb.fsDeviceAttr |= VDISKType; // -> RAM disk
2871 }
2872 }
2873 }
2874
2875
2876 /*
2877 * Determin return value.
2878 */
2879 if (bpb.fsDeviceAttr & FloppyType)
2880 {
2881 ulDriveType = DRIVE_REMOVABLE_W;
2882 /* update floppy cache if A or B */
2883 if (ulDrive <= 1)
2884 ulFloppyMask |= 1 << ulDrive;
2885 }
2886 else if (bpb.fsDeviceAttr & CDType)
2887 {
2888 ulDriveType = DRIVE_CDROM_W;
2889 /* update cdrom cache */
2890 ulCDROMMask |= 1 << ulDrive;
2891 }
2892 else if (bpb.fsDeviceAttr & LanType)
2893 ulDriveType = DRIVE_REMOTE_W;
2894 else if (bpb.fsDeviceAttr & VDISKType)
2895 ulDriveType = DRIVE_RAMDISK_W;
2896 else if (bpb.fsDeviceAttr & OpticalType || bpb.bDeviceType == DEVTYPE_OPTICAL)
2897 ulDriveType = DRIVE_FIXED_W;
2898 else if (bpb.bDeviceType == DEVTYPE_FIXED)
2899 ulDriveType = DRIVE_FIXED_W;
2900 else
2901 ulDriveType = DRIVE_UNKNOWN_W;
2902
2903 return ulDriveType;
2904}
2905//******************************************************************************
2906//Returns bit map where with the mapping of the logical drives
2907//******************************************************************************
2908ULONG OSLibGetLogicalDrives()
2909{
2910 ULONG ulDriveNum = 0; /* Drive number (A=1, B=2, C=3, ...) */
2911 ULONG ulDriveMap = 0; /* Mapping of valid drives */
2912 APIRET rc;
2913
2914 rc = DosQueryCurrentDisk(&ulDriveNum, &ulDriveMap);
2915 if(rc) {
2916 DebugInt3();
2917 SetLastError(error2WinError(rc));
2918 return 0;
2919 }
2920 return ulDriveMap;
2921}
2922//******************************************************************************
2923//******************************************************************************
2924ULONG OSLibDosQueryCurrentDisk()
2925
2926{
2927 ULONG ulDriveNum = 0; /* Drive number (A=1, B=2, C=3, ...) */
2928 ULONG ulDriveMap = 0; /* Mapping of valid drives */
2929 APIRET rc;
2930
2931 rc = DosQueryCurrentDisk(&ulDriveNum, &ulDriveMap);
2932 if(rc) {
2933 DebugInt3();
2934 SetLastError(error2WinError(rc));
2935 return 0;
2936 }
2937 return ulDriveNum;
2938}
2939//******************************************************************************
2940//******************************************************************************
2941BOOL OSLibDosCreatePipe(PHANDLE phfRead,
2942 PHANDLE phfWrite,
2943 LPSECURITY_ATTRIBUTES lpsa,
2944 DWORD dwSize)
2945{
2946 APIRET rc;
2947
2948 dprintf(("DosCreatePipe(%08xh,%08xh,%08xh)\n",
2949 phfRead,
2950 phfWrite,
2951 dwSize));
2952
2953 // select default buffer size
2954 if (dwSize == 0)
2955 dwSize = 4096;
2956
2957 rc = DosCreatePipe(phfRead,
2958 phfWrite,
2959 dwSize);
2960 dprintf(("DosCreatePipe rc=%d",rc));
2961 if (rc)
2962 {
2963 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER_W));
2964 return -1; // INVALID_HANDLE_VALUE
2965 }
2966 SetLastError(ERROR_SUCCESS_W);
2967 return NO_ERROR;
2968}
2969//******************************************************************************
2970//******************************************************************************
2971DWORD SYSTEM OSLibDosDevIOCtl( DWORD hFile, DWORD dwCat, DWORD dwFunc,
2972 PVOID pParm, DWORD dwParmMaxLen, DWORD *pdwParmLen,
2973 PVOID pData, DWORD dwDataMaxLen, DWORD *pdwDataLen)
2974{
2975 APIRET rc;
2976 PVOID pTiledParm = pParm;
2977 BOOL flagTiledParm = FALSE;
2978 PVOID pTiledData = pData;
2979 BOOL flagTiledData = FALSE;
2980
2981#if 1
2982 /*
2983 * Quick and Dirty Fix!
2984 * TO BE REMOVED!
2985 *
2986 * On some VPC installation without CDROM we seem to
2987 * use a concidrable amount of time during Win2k shutdown.
2988 * No idea why, but it has to do with CDROM we think.
2989 *
2990 * So, let's just fail all IOCtls to CD01 if there aren't any
2991 * CDROMs in the system.
2992 *
2993 */
2994
2995 /*
2996 * Check for CD drives
2997 * We don't have to this everytime. I mean, the os2cdrom.dmd is
2998 * exactly very dynamic when it comes to this info.
2999 */
3000 if (cdDrvLtr.drive_count == 0xffff)
3001 {
3002 HFILE hCDRom2;
3003 ULONG ulAction = 0;
3004
3005 if (DosOpen("\\DEV\\CD-ROM2$", &hCDRom2, &ulAction, 0,
3006 FILE_NORMAL, OPEN_ACTION_OPEN_IF_EXISTS,
3007 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY | OPEN_FLAGS_NOINHERIT, NULL)
3008 == NO_ERROR)
3009 {
3010 ULONG cbData = sizeof(cdDrvLtr);
3011 rc = DosDevIOCtl(hCDRom2,
3012 IOC_CDROM_2,
3013 IOCD_RETURN_DRIVE_LETTER,
3014 NULL, 0, NULL,
3015 (PVOID)&cdDrvLtr, sizeof(cdDrvLtr), &cbData);
3016 DosClose(hCDRom2);
3017 }
3018 else
3019 cdDrvLtr.drive_count = 0;
3020 }
3021
3022 if ( cdDrvLtr.drive_count == 0
3023 && (dwCat == IOCTL_CDROMDISK
3024 || (dwCat == IOCTL_CDROMAUDIO
3025 && dwParmMaxLen >= 4 && strncmp((char*)pParm, "CD01", 4))
3026 )
3027 )
3028 {
3029 /* just return some error code */
3030 return ERROR_BAD_COMMAND;
3031 }
3032
3033#endif
3034
3035#define MEM_TILED_CEILING 0x1fffffff
3036
3037 // bounce buffer support
3038 // make sure no parameter or data buffer can pass the tiled memory region
3039 // barrier (usually 512MB). OS/2 kernel does not correctly translate these
3040 // addresses to a 16:16 address used in device driver land. In fact,
3041 // DosDevIOCtl is not a high memory enabled API!
3042
3043 if (pTiledParm && (((DWORD)pTiledParm + max(dwParmMaxLen, *pdwParmLen)) > MEM_TILED_CEILING))
3044 {
3045 rc = DosAllocMem(&pTiledParm, dwParmMaxLen, PAG_READ | PAG_WRITE);
3046 if (rc)
3047 goto _exit_ioctl;
3048
3049 flagTiledParm = TRUE;
3050 }
3051
3052 if (pTiledData && (((DWORD)pTiledData + max(dwDataMaxLen, *pdwDataLen)) > MEM_TILED_CEILING))
3053 {
3054 rc = DosAllocMem(&pTiledData, dwDataMaxLen, PAG_READ | PAG_WRITE);
3055 if (rc)
3056 goto _exit_ioctl;
3057
3058 flagTiledData = TRUE;
3059 }
3060
3061 // copy data from real buffers to
3062 // bounce buffers if necessary
3063 if (pTiledParm != pParm)
3064 memcpy(pTiledParm, pParm, *pdwParmLen);
3065
3066 if (pTiledData != pData)
3067 memcpy(pTiledData, pData, *pdwDataLen);
3068
3069
3070 rc = DosDevIOCtl( (HFILE)hFile, dwCat, dwFunc,
3071 pParm, dwParmMaxLen, pdwParmLen,
3072 pData, dwDataMaxLen, pdwDataLen);
3073
3074 // copy data from bounce buffers to real
3075 // target buffers if necessary
3076 if (pTiledParm != pParm)
3077 memcpy(pParm, pTiledParm, *pdwParmLen);
3078
3079 if (pTiledData != pData)
3080 memcpy(pData, pTiledData, *pdwDataLen);
3081
3082
3083 _exit_ioctl:
3084
3085 // deallocate bounce buffers
3086 if (flagTiledParm)
3087 DosFreeMem(pTiledParm);
3088
3089 if (flagTiledData)
3090 DosFreeMem(pTiledData);
3091
3092 rc = error2WinError(rc, ERROR_INVALID_HANDLE);
3093 SetLastError(rc);
3094 return (DWORD)rc;
3095}
3096
3097/**
3098 * Pure wrapper for DosQueryModulName which returns the OS/2 returncode.
3099 * @returns Returncode from DosQueryModuleName.
3100 * @param hModule Handle of the module which name we query.
3101 * @param cchName Length of the output name buffer.
3102 * @param pszname Pointer to the output name buffer.
3103 * @status Completely implemented.
3104 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
3105 */
3106ULONG OSLibDosQueryModuleName(ULONG hModule, int cchName, char *pszName)
3107{
3108 return DosQueryModuleName(hModule, cchName, pszName);
3109}
3110
3111
3112HINSTANCE OSLibDosLoadModule(LPSTR szModName)
3113{
3114 APIRET rc;
3115 HMODULE hModule = NULLHANDLE;
3116 char name[ CCHMAXPATH ];
3117
3118 rc = DosLoadModule(name, CCHMAXPATH, szModName, &hModule);
3119 if(rc) {
3120 SetLastError(error2WinError(rc,ERROR_FILE_NOT_FOUND));
3121 return 0;
3122 }
3123 SetLastError(ERROR_SUCCESS_W);
3124 return hModule;
3125}
3126//******************************************************************************
3127//******************************************************************************
3128void OSLibDosFreeModule(HINSTANCE hinst)
3129{
3130 DosFreeModule(hinst);
3131}
3132//******************************************************************************
3133//******************************************************************************
3134ULONG OSLibDosQuerySysInfo(ULONG iStart, ULONG iLast, PVOID pBuf, ULONG cbBuf)
3135{
3136 APIRET rc;
3137
3138 rc = DosQuerySysInfo(iStart, iLast, pBuf, cbBuf);
3139 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
3140 return rc;
3141}
3142//******************************************************************************
3143//returned length is number of characters required or used for current dir
3144//*excluding* terminator
3145//******************************************************************************
3146ULONG OSLibDosQueryDir(DWORD length, LPSTR lpszCurDir)
3147{
3148 ULONG drivemap, currentdisk, len;
3149 char *lpszCurDriveAndDir = lpszCurDir +3;
3150 APIRET rc;
3151
3152 len = (length > 3) ? length - 3 : 0;
3153
3154 rc = DosQueryCurrentDir(0, lpszCurDriveAndDir, &len);
3155 if(rc != ERROR_BUFFER_OVERFLOW)
3156 {
3157 if(rc)
3158 {
3159 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER));
3160 return 0;
3161 }
3162 len = strlen(lpszCurDriveAndDir) + 3;
3163
3164 // Dir returned by DosQueryCurDir doesn't include drive, so add it
3165 DosQueryCurrentDisk(&currentdisk, &drivemap);
3166
3167 if(isupper(lpszCurDir[3])) {
3168 lpszCurDir[0] = (char)('A' - 1 + currentdisk);
3169 }
3170 else lpszCurDir[0] = (char)('a' - 1 + currentdisk);
3171
3172 lpszCurDir[1] = ':';
3173 lpszCurDir[2] = '\\';
3174 }
3175 else len += 3; // + 3 since DosQueryCurDir doesn't include drive
3176
3177 SetLastError(ERROR_SUCCESS_W);
3178 return len;
3179}
3180//******************************************************************************
3181//******************************************************************************
3182BOOL OSLibDosBeep(DWORD ulFreq, DWORD ulDuration)
3183{
3184 APIRET rc;
3185
3186 if (ulDuration == -1)
3187 {
3188 SetLastError(ERROR_NOT_SUPPORTED_W);
3189 return FALSE;
3190 }
3191 rc = DosBeep(ulFreq, ulDuration);
3192 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
3193
3194 return (rc == 0);
3195}
3196//******************************************************************************
3197//******************************************************************************
3198ULONG OSLibDosGetModuleFileName(HMODULE hModule, LPTSTR lpszPath, DWORD cchPath)
3199{
3200 PTIB pTIB;
3201 PPIB pPIB;
3202 APIRET rc;
3203
3204 if(hModule == -1 || hModule == 0)
3205 {
3206 DosGetInfoBlocks(&pTIB, &pPIB);
3207 hModule = pPIB->pib_hmte;
3208 }
3209 *lpszPath = 0;
3210 rc = DosQueryModuleName(hModule, cchPath, lpszPath);
3211
3212 DWORD len = strlen(lpszPath);
3213 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
3214 return len;
3215}
3216//******************************************************************************
3217//******************************************************************************
3218ULONG OSLibDosGetProcAddress(HMODULE hModule, LPCSTR lpszProc)
3219{
3220 APIRET rc;
3221 PFN pfn = NULL;
3222 ULONG ordinal = (((ULONG)lpszProc) <= 0xFFFF) ? (ULONG)lpszProc : 0;
3223 HMODULE hmod = (HMODULE)hModule;
3224
3225 rc = DosQueryProcAddr( hmod, ordinal, (PSZ)lpszProc, &pfn );
3226 if(rc == ERROR_INVALID_HANDLE && pfn == NULL) {
3227 CHAR pszError[32], pszModule[CCHMAXPATH];
3228
3229 if(DosQueryModuleName( hmod, CCHMAXPATH, pszModule ) == 0 &&
3230 DosLoadModule( pszError, 32, pszModule, &hmod ) == 0)
3231 {
3232 rc = DosQueryProcAddr(hmod, ordinal, (PSZ)lpszProc, &pfn);
3233 }
3234 }
3235 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
3236
3237 return (ULONG)pfn;
3238}
3239//******************************************************************************
3240//******************************************************************************
3241BOOL OSLibDosSetThreadAffinity(DWORD dwThreadAffinityMask)
3242{
3243 static PROC_DosSetThreadAffinity pfnDosSetThreadAffinity = NULL;
3244 static BOOL fInit = FALSE;
3245 MPAFFINITY mask;
3246 APIRET rc;
3247
3248 if(fInit == FALSE && pfnDosSetThreadAffinity == NULL)
3249 {
3250 ULONG nrCPUs;
3251
3252 rc = DosQuerySysInfo(QSV_NUMPROCESSORS, QSV_NUMPROCESSORS, &nrCPUs, sizeof(nrCPUs));
3253 if (rc != 0 || nrCPUs == 1)
3254 {//not supported
3255 fInit = TRUE;
3256 SetLastError(ERROR_SUCCESS_W);
3257 return TRUE;
3258 }
3259
3260 HMODULE hDoscalls;
3261 if(DosQueryModuleHandle("DOSCALLS", &hDoscalls) == NO_ERROR) {
3262 DosQueryProcAddr(hDoscalls, 564, NULL, (PFN *)&pfnDosSetThreadAffinity);
3263 }
3264 fInit = TRUE;
3265 }
3266 if(fInit && pfnDosSetThreadAffinity == NULL) {
3267 SetLastError(ERROR_SUCCESS_W);
3268 return TRUE;
3269 }
3270 USHORT sel = RestoreOS2FS();
3271
3272 mask.mask[0] = dwThreadAffinityMask;
3273 mask.mask[1] = 0; //TODO: this might not be a good idea, but then again, not many people have > 32 cpus
3274
3275 rc = pfnDosSetThreadAffinity(&mask);
3276 SetFS(sel);
3277
3278 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER));
3279 return (rc == NO_ERROR);
3280}
3281//******************************************************************************
3282//******************************************************************************
3283BOOL OSLibDosQueryAffinity(DWORD fMaskType, DWORD *pdwThreadAffinityMask)
3284{
3285 static PROC_DosQueryThreadAffinity pfnDosQueryThreadAffinity = NULL;
3286 static BOOL fInit = FALSE;
3287 MPAFFINITY mask;
3288 APIRET rc;
3289
3290 if(fInit == FALSE && pfnDosQueryThreadAffinity == NULL)
3291 {
3292 ULONG nrCPUs;
3293
3294 rc = DosQuerySysInfo(QSV_NUMPROCESSORS, QSV_NUMPROCESSORS, &nrCPUs, sizeof(nrCPUs));
3295 if (rc != 0 || nrCPUs == 1)
3296 {//not supported
3297 fInit = TRUE;
3298 *pdwThreadAffinityMask = 1;
3299 SetLastError(ERROR_SUCCESS_W);
3300 return TRUE;
3301 }
3302
3303 HMODULE hDoscalls;
3304 if(DosQueryModuleHandle("DOSCALLS", &hDoscalls) == NO_ERROR) {
3305 DosQueryProcAddr(hDoscalls, 563, NULL, (PFN *)&pfnDosQueryThreadAffinity);
3306 }
3307 fInit = TRUE;
3308 }
3309 if(fInit && pfnDosQueryThreadAffinity == NULL) {
3310 *pdwThreadAffinityMask = 1;
3311 SetLastError(ERROR_SUCCESS_W);
3312 return TRUE;
3313 }
3314
3315 ULONG scope = (fMaskType == MASK_SYSTEM) ? AFNTY_SYSTEM : AFNTY_THREAD;
3316
3317 USHORT sel = RestoreOS2FS();
3318
3319 rc = pfnDosQueryThreadAffinity(scope, &mask);
3320 SetFS(sel);
3321
3322 if(rc == NO_ERROR) {
3323 *pdwThreadAffinityMask = mask.mask[0];
3324 }
3325
3326 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER));
3327 return (rc == NO_ERROR);
3328}
3329//******************************************************************************
3330//******************************************************************************
3331void OSLibDosSleep(ULONG msecs)
3332{
3333 DosSleep(msecs);
3334}
3335//******************************************************************************
3336//******************************************************************************
3337DWORD OSLibDosDevConfig(PVOID pdevinfo,
3338 ULONG item)
3339{
3340 return (DWORD)DosDevConfig(pdevinfo, item);
3341}
3342//******************************************************************************
3343//******************************************************************************
3344DWORD OSLibDosGetNumPhysDrives()
3345{
3346 USHORT usNumDrives = 0; /* Data return buffer */
3347 ULONG ulDataLen = sizeof(USHORT); /* Data return buffer length */
3348 APIRET rc = NO_ERROR; /* Return code */
3349
3350 /* Request a count of the number of partitionable disks in the system */
3351
3352 rc = DosPhysicalDisk(INFO_COUNT_PARTITIONABLE_DISKS,
3353 &usNumDrives,
3354 ulDataLen,
3355 NULL, /* No parameter for this function */
3356 0L);
3357
3358 if (rc != NO_ERROR) {
3359 dprintf(("DosPhysicalDisk error: return code = %u\n", rc));
3360 return 0;
3361 }
3362 else {
3363 dprintf(("DosPhysicalDisk: %u partitionable disk(s)\n",usNumDrives));
3364 }
3365 return usNumDrives;
3366}
3367//******************************************************************************
3368//******************************************************************************
3369
Note: See TracBrowser for help on using the repository browser.