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

Last change on this file since 21407 was 21407, checked in by dmik, 15 years ago

Removed accidentally committed garbage.

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