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

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