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

Last change on this file since 21329 was 21329, checked in by vladest, 16 years ago

Added functionality, required for Flash10 to kernel32

File size: 108.7 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#if 0
1332 // PH Note: for a negative 32-bit seek, the OS/2 64-bit version
1333 // needs to be skipped.
1334 if( (f64BitIO) && (OffsetHigh) &&
1335 (*OffsetHigh != 0xAAAAAAAA) &&
1336 (*OffsetHigh != 0)) //workaround for flash10 video
1337 {
1338 offsetL.ulLo = OffsetLow;
1339 offsetL.ulHi = (OffsetHigh) ? *OffsetHigh : 0;
1340 rc = OdinDosSetFilePtrL(hFile, offsetL, method, &newoffsetL);
1341 if(OffsetHigh) {
1342 *OffsetHigh = newoffsetL.ulHi;
1343 }
1344 newoffset = newoffsetL.ulLo;
1345 }
1346 else
1347#endif
1348 rc = DosSetFilePtr(hFile, OffsetLow, method, &newoffset);
1349
1350 if(rc)
1351 {
1352 SetLastError(error2WinError(rc));
1353 return -1;
1354 }
1355 SetLastError(ERROR_SUCCESS_W);
1356 return newoffset;
1357}
1358//******************************************************************************
1359//******************************************************************************
1360BOOL OSLibDosSetEndOfFile(DWORD hFile)
1361{
1362 ULONG newFilePos;
1363 LONGLONG FilePosL = {0,0};
1364 LONGLONG newFilePosL;
1365 APIRET rc;
1366
1367 if(f64BitIO) {
1368 rc = OdinDosSetFilePtrL(hFile, FilePosL, FILE_CURRENT, &newFilePosL);
1369 if(rc == 0) {
1370 rc = OdinDosSetFileSizeL(hFile, newFilePosL);
1371 }
1372 }
1373 else {
1374 rc = DosSetFilePtr(hFile, 0, FILE_CURRENT, &newFilePos);
1375 if(rc == 0) {
1376 rc = DosSetFileSize(hFile, newFilePos);
1377 }
1378 }
1379 if(rc) {
1380 SetLastError(error2WinError(rc));
1381 return FALSE;
1382 }
1383 SetLastError(ERROR_SUCCESS_W);
1384 return TRUE;
1385}
1386//******************************************************************************
1387//******************************************************************************
1388BOOL OSLibDosGetFileInformationByHandle(DWORD hFile, BY_HANDLE_FILE_INFORMATION* pInfo)
1389{
1390 APIRET rc;
1391
1392 if(f64BitIO)
1393 {
1394 FILESTATUS4L statusL = { 0 };
1395
1396 rc = DosQueryFileInfo(hFile, FIL_QUERYEASIZEL,
1397 &statusL, sizeof(statusL));
1398 if(rc == NO_ERROR)
1399 {
1400 pInfo->dwFileAttributes = 0;
1401 if(!(statusL.attrFile & NOT_NORMAL))
1402 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_NORMAL_W;
1403 if(statusL.attrFile & FILE_READONLY)
1404 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_READONLY_W;
1405 if(statusL.attrFile & FILE_HIDDEN)
1406 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN_W;
1407 if(statusL.attrFile & FILE_SYSTEM)
1408 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_SYSTEM_W;
1409 if(statusL.attrFile & FILE_DIRECTORY)
1410 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY_W;
1411 if(statusL.attrFile & FILE_ARCHIVED)
1412 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_ARCHIVE_W;
1413
1414 pmDateTimeToFileTime(&statusL.fdateCreation,
1415 &statusL.ftimeCreation,
1416 &pInfo->ftCreationTime);
1417 pmDateTimeToFileTime(&statusL.fdateLastAccess,
1418 &statusL.ftimeLastAccess,
1419 &pInfo->ftLastAccessTime);
1420 pmDateTimeToFileTime(&statusL.fdateLastWrite,
1421 &statusL.ftimeLastWrite,
1422 &pInfo->ftLastWriteTime);
1423
1424 pInfo->nFileSizeHigh = statusL.cbFile.ulHi;
1425 pInfo->nFileSizeLow = statusL.cbFile.ulLo;
1426 pInfo->dwVolumeSerialNumber = 0; //todo
1427 pInfo->nNumberOfLinks = 1;
1428 pInfo->nFileIndexHigh = 0;
1429 pInfo->nFileIndexLow = 0;
1430 }
1431 }
1432 else
1433 {
1434 FILESTATUS4 status = { 0 };
1435
1436 rc = DosQueryFileInfo(hFile, FIL_QUERYEASIZE, &status,
1437 sizeof(status));
1438 if(rc == NO_ERROR)
1439 {
1440 pInfo->dwFileAttributes = 0;
1441 if(!(status.attrFile & NOT_NORMAL))
1442 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_NORMAL_W;
1443 if(status.attrFile & FILE_READONLY)
1444 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_READONLY_W;
1445 if(status.attrFile & FILE_HIDDEN)
1446 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_HIDDEN_W;
1447 if(status.attrFile & FILE_SYSTEM)
1448 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_SYSTEM_W;
1449 if(status.attrFile & FILE_DIRECTORY)
1450 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_DIRECTORY_W;
1451 if(status.attrFile & FILE_ARCHIVED)
1452 pInfo->dwFileAttributes |= FILE_ATTRIBUTE_ARCHIVE_W;
1453
1454 pmDateTimeToFileTime(&status.fdateCreation,
1455 &status.ftimeCreation,
1456 &pInfo->ftCreationTime);
1457 pmDateTimeToFileTime(&status.fdateLastAccess,
1458 &status.ftimeLastAccess,
1459 &pInfo->ftLastAccessTime);
1460 pmDateTimeToFileTime(&status.fdateLastWrite,
1461 &status.ftimeLastWrite,
1462 &pInfo->ftLastWriteTime);
1463
1464 pInfo->nFileSizeHigh = 0;
1465 pInfo->nFileSizeLow = status.cbFile;
1466 pInfo->dwVolumeSerialNumber = 0; //todo
1467 pInfo->nNumberOfLinks = 1;
1468 pInfo->nFileIndexHigh = 0;
1469 pInfo->nFileIndexLow = 0;
1470 }
1471 }
1472 if(rc) {
1473 SetLastError(error2WinError(rc));
1474 return FALSE;
1475 }
1476 SetLastError(ERROR_SUCCESS_W);
1477 return TRUE;
1478}
1479//******************************************************************************
1480//******************************************************************************
1481BOOL OSLibDosSetFileTime(DWORD hFile, LPFILETIME pFT1,
1482 LPFILETIME pFT2, LPFILETIME pFT3)
1483{
1484 FILESTATUS3 fileInfo;
1485 APIRET rc;
1486
1487 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &fileInfo, sizeof(fileInfo));
1488
1489 if (rc == NO_ERROR)
1490 {
1491 if (pFT1) pmFileTimeToDateTime(pFT1, &fileInfo.fdateCreation, &fileInfo.ftimeCreation);
1492 if (pFT2) pmFileTimeToDateTime(pFT2, &fileInfo.fdateLastAccess,&fileInfo.ftimeLastAccess);
1493 if (pFT3) pmFileTimeToDateTime(pFT3, &fileInfo.fdateLastWrite, &fileInfo.ftimeLastWrite);
1494
1495 rc = DosSetFileInfo(hFile, FIL_STANDARD, &fileInfo, sizeof(fileInfo));
1496 }
1497
1498 if(rc)
1499 {
1500 SetLastError(error2WinError(rc));
1501 return FALSE;
1502 }
1503 SetLastError(ERROR_SUCCESS_W);
1504 return TRUE;
1505}
1506//******************************************************************************
1507//******************************************************************************
1508BOOL OSLibDosGetFileTime(DWORD hFile, LPFILETIME pFT1,
1509 LPFILETIME pFT2, LPFILETIME pFT3)
1510{
1511 FILESTATUS3 fileInfo;
1512 APIRET rc;
1513
1514 rc = DosQueryFileInfo(hFile, FIL_STANDARD, &fileInfo, sizeof(fileInfo));
1515
1516 if(rc == NO_ERROR)
1517 {
1518 if (pFT1) pmDateTimeToFileTime(&fileInfo.fdateCreation, &fileInfo.ftimeCreation, pFT1);
1519 if (pFT2) pmDateTimeToFileTime(&fileInfo.fdateLastAccess,&fileInfo.ftimeLastAccess,pFT2);
1520 if (pFT3) pmDateTimeToFileTime(&fileInfo.fdateLastWrite, &fileInfo.ftimeLastWrite, pFT3);
1521 }
1522 if(rc)
1523 {
1524 SetLastError(error2WinError(rc));
1525 return FALSE;
1526 }
1527 SetLastError(ERROR_SUCCESS_W);
1528 return TRUE;
1529}
1530//******************************************************************************
1531//******************************************************************************
1532DWORD OSLibDosSetFilePtr2(DWORD hFile, DWORD offset, DWORD method)
1533{
1534 DWORD newoffset;
1535 APIRET rc;
1536
1537
1538 rc = DosSetFilePtr(hFile, offset, method, &newoffset);
1539 if(rc) {
1540 dprintf(("DosSetFilePtr Error rc:%d", rc));
1541 return -1;
1542 }
1543 else return newoffset;
1544}
1545//******************************************************************************
1546//******************************************************************************
1547DWORD OSLibDosDupHandle(DWORD hFile, DWORD *hNew)
1548{
1549 DWORD dwNewHandle = -1, ret;
1550
1551 //Use the stack for storing the new handle; DosDupHandle doesn't like high
1552 //addresses
1553 ret = DosDupHandle(hFile, &dwNewHandle);
1554 *hNew = dwNewHandle;
1555 return ret;
1556}
1557//******************************************************************************
1558//******************************************************************************
1559DWORD OSLibDosSetFHState(DWORD hFile, DWORD dwFlags)
1560{
1561 DWORD ulMode;
1562 APIRET rc;
1563
1564 rc = DosQueryFHState(hFile, &ulMode);
1565 if(rc != NO_ERROR) return error2WinError(rc);
1566
1567 //turn off non-participating bits
1568 ulMode &= 0x7F88;
1569
1570 if(dwFlags & HANDLE_FLAG_INHERIT_W) {
1571 ulMode &= ~OPEN_FLAGS_NOINHERIT;
1572 }
1573 else
1574 ulMode |= OPEN_FLAGS_NOINHERIT;
1575
1576 rc = DosSetFHState(hFile, ulMode);
1577 return error2WinError(rc);
1578}
1579//******************************************************************************
1580//Returns time spent in kernel & user mode in milliseconds
1581//******************************************************************************
1582BOOL OSLibDosQueryProcTimes(DWORD procid, ULONG *kerneltime, ULONG *usertime)
1583{
1584 APIRET rc;
1585 char *buf;
1586 ULONG size;
1587 ULONG nrthreads = 4;
1588
1589tryagain:
1590 size = sizeof(QTOPLEVEL)+sizeof(QGLOBAL)+sizeof(QPROCESS) + nrthreads*sizeof(QTHREAD);
1591 buf = (char *)malloc(size);
1592 rc = DosQuerySysState(0x1, RESERVED, procid, RESERVED, (PCHAR)buf, size);
1593
1594 if(rc) {
1595 free(buf);
1596 if(rc == ERROR_BUFFER_OVERFLOW) {
1597 nrthreads += 4;
1598 goto tryagain;
1599 }
1600 return FALSE;
1601 }
1602 PQTOPLEVEL top = (PQTOPLEVEL)buf;
1603
1604 *kerneltime = 0;
1605 *usertime = 0;
1606 for(int i=0;i<top->procdata->threadcnt;i++) {
1607 *kerneltime += top->procdata->threads[i].systime;
1608 *usertime += top->procdata->threads[i].usertime;
1609 }
1610 free(buf);
1611 return TRUE;
1612}
1613//******************************************************************************
1614//******************************************************************************
1615// TODO: implement SecurityAttributes parameter
1616DWORD OSLibDosCreateNamedPipe(LPCTSTR lpName,
1617 DWORD dwOpenMode,
1618 DWORD dwPipeMode,
1619 DWORD nMaxInstances,
1620 DWORD nOutBufferSize,
1621 DWORD nInBufferSize,
1622 DWORD nDefaultTimeOut,
1623 LPSECURITY_ATTRIBUTES lpSecurityAttributes)
1624{ DWORD dwOS2Mode = NP_NOINHERIT; //default is not inherited by child processes
1625 DWORD dwOS2PipeMode = 0;
1626 LPSTR lpOS2Name;
1627 DWORD hPipe;
1628 DWORD rc, ulAction;
1629
1630 if ((dwOpenMode & PIPE_ACCESS_DUPLEX_W) == PIPE_ACCESS_DUPLEX_W)
1631 dwOS2Mode |= NP_ACCESS_DUPLEX;
1632 else
1633 if (dwOpenMode & PIPE_ACCESS_INBOUND_W)
1634 dwOS2Mode |= NP_ACCESS_INBOUND;
1635 else
1636 if (dwOpenMode & PIPE_ACCESS_OUTBOUND_W)
1637 dwOS2Mode |= NP_ACCESS_OUTBOUND;
1638 // TODO:
1639 // if(dwOpenMode & FILE_FLAG_OVERLAPPED)
1640 // if(dwOpenMode & WRITE_DAC)
1641 // if(dwOpenMode & WRITE_OWNER)
1642 // if(dwOpenMode & ACCESS_SYSTEM_SECURITY)
1643 if(dwOpenMode & FILE_FLAG_WRITE_THROUGH_W)
1644 dwOS2Mode |= NP_WRITEBEHIND; // FIXME: I'm not sure!
1645
1646 if (dwPipeMode & PIPE_WAIT_W)
1647 dwOS2PipeMode |= NP_WAIT;
1648 if (dwPipeMode & PIPE_NOWAIT_W)
1649 dwOS2PipeMode |= NP_NOWAIT;
1650 if (dwPipeMode & PIPE_READMODE_BYTE_W)
1651 dwOS2PipeMode |= NP_READMODE_BYTE;
1652 if (dwPipeMode & PIPE_READMODE_MESSAGE_W)
1653 dwOS2PipeMode |= NP_READMODE_MESSAGE;
1654 if (dwPipeMode & PIPE_TYPE_BYTE_W)
1655 dwOS2PipeMode |= NP_TYPE_BYTE;
1656 if (dwPipeMode & PIPE_TYPE_MESSAGE_W)
1657 dwOS2PipeMode |= NP_TYPE_MESSAGE;
1658
1659 if (nMaxInstances>0xff)
1660 {
1661 SetLastError(ERROR_INVALID_PARAMETER_W); // ERROR_INVALID_PARAMETER
1662 return -1; // INVALID_HANDLE_VALUE
1663 }
1664 dwOS2PipeMode |= nMaxInstances;
1665
1666 if (strstr(lpName,"\\\\."))
1667 {
1668 // If pipe is created on the local machine
1669 // we must delete string \\. because
1670 // in Windows named pipes scheme is a \\.\PIPE\pipename
1671 // but in OS/2 only \PIPE\pipename
1672 lpOS2Name = (LPSTR)lpName + 3;
1673 }
1674 else lpOS2Name = (LPSTR)lpName;
1675
1676 dprintf(("DosCreateNPipe(%s,%x,%x,%x,%x,%x)",lpOS2Name,dwOS2Mode,dwOS2PipeMode,nInBufferSize,nOutBufferSize,nDefaultTimeOut));
1677
1678 //if the windows app tries to open another instance of an existing pipe, then
1679 //we must use DosOpen here. So first try DosOpen, if that fails then we can
1680 //create the named pipe
1681 rc = DosOpen(lpOS2Name, &hPipe, &ulAction, 0, FILE_NORMAL, FILE_OPEN,
1682 ((dwOpenMode & PIPE_ACCESS_INBOUND_W) ? OPEN_ACCESS_READWRITE : OPEN_ACCESS_READONLY) |
1683 OPEN_SHARE_DENYNONE | OPEN_FLAGS_NOINHERIT, NULL);
1684
1685 if(rc == NO_ERROR) {
1686#if 0
1687 //TODO:
1688 if(dwOpenMode & FILE_FLAG_FIRST_PIPE_INSTANCE_W) {
1689 DosClose(hPipe);
1690 SetLastError(ERROR_ALREADY_EXISTS_W);
1691 return -1;
1692 }
1693 else {
1694#endif
1695 dprintf(("Opening of existing named pipe succeeded"));
1696 SetLastError(ERROR_SUCCESS_W);
1697 return hPipe;
1698// }
1699 }
1700
1701 rc=DosCreateNPipe(lpOS2Name,
1702 &hPipe,
1703 dwOS2Mode,
1704 dwOS2PipeMode,
1705 nInBufferSize,
1706 nInBufferSize,
1707 nDefaultTimeOut); // Timeouts must be tested!
1708
1709 dprintf(("DosCreateNPipe rc=%d",rc));
1710 if (rc)
1711 {
1712 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER_W));
1713 return -1; // INVALID_HANDLE_VALUE
1714 }
1715 SetLastError(ERROR_SUCCESS_W);
1716 return hPipe;
1717}
1718//******************************************************************************
1719//******************************************************************************
1720BOOL OSLibSetNamedPipeState(DWORD hNamedPipe, DWORD dwPipeMode)
1721{
1722 ULONG dwOS2PipeMode = 0;
1723 APIRET rc;
1724
1725 if (dwPipeMode & PIPE_WAIT_W)
1726 dwOS2PipeMode |= NP_WAIT;
1727 if (dwPipeMode & PIPE_NOWAIT_W)
1728 dwOS2PipeMode |= NP_NOWAIT;
1729 if (dwPipeMode & PIPE_READMODE_BYTE_W)
1730 dwOS2PipeMode |= NP_READMODE_BYTE;
1731 if (dwPipeMode & PIPE_READMODE_MESSAGE_W)
1732 dwOS2PipeMode |= NP_READMODE_MESSAGE;
1733
1734 rc = DosSetNPHState(hNamedPipe, dwOS2PipeMode);
1735 if(rc) {
1736 SetLastError(error2WinError(rc, ERROR_INVALID_PARAMETER_W));
1737 return FALSE;
1738 }
1739 SetLastError(ERROR_SUCCESS_W);
1740 return TRUE;
1741}
1742//******************************************************************************
1743//******************************************************************************
1744DWORD OSLibDosOpenPipe(LPCTSTR lpName,
1745 DWORD fuAccess,
1746 DWORD fuShare,
1747 LPSECURITY_ATTRIBUTES lpSecurityAttributes,
1748 DWORD fuCreate,
1749 DWORD fuAttrFlags)
1750{
1751 LPSTR lpOS2Name;
1752 ULONG hPipe;
1753 ULONG rc, ulAction;
1754 ULONG openFlag = 0;
1755 ULONG openMode = OPEN_FLAGS_NOINHERIT; //default is not inherited by child processes
1756
1757
1758 switch(fuCreate)
1759 {
1760 case CREATE_NEW_W:
1761 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_FAIL_IF_EXISTS;
1762 break;
1763 case CREATE_ALWAYS_W:
1764 /* kso 2000-11-26: Not sure if OPEN_ACTION_REPLACE_IF_EXISTS is correct here! It is correct according to
1765 * MSDN, but not according to "The Win32 API SuperBible". Anyway I haven't got time to check it out in
1766 * NT now.
1767 * The problem is that OPEN_ACTION_REPLACE_IF_EXISTS requires write access. It failes with
1768 * rc = ERROR_ACCESS_DENIED (5). Quick fix, use OPEN_IF_EXIST if readonly access.
1769 */
1770 if (fuAccess & GENERIC_WRITE_W)
1771 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
1772 else
1773 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
1774 break;
1775 case OPEN_EXISTING_W:
1776 openFlag |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
1777 break;
1778 case OPEN_ALWAYS_W:
1779 openFlag |= OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
1780 break;
1781 case TRUNCATE_EXISTING_W:
1782 openFlag |= OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS;
1783 break;
1784 }
1785
1786 if(fuAttrFlags & FILE_FLAG_WRITE_THROUGH_W) openMode |= OPEN_FLAGS_WRITE_THROUGH;
1787 if(fuAttrFlags & FILE_FLAG_NO_BUFFERING_W) openMode |= OPEN_FLAGS_NO_CACHE;
1788 if(fuAttrFlags & FILE_FLAG_RANDOM_ACCESS_W) openMode |= OPEN_FLAGS_RANDOM;
1789 if(fuAttrFlags & FILE_FLAG_SEQUENTIAL_SCAN_W) openMode |= OPEN_FLAGS_SEQUENTIAL;
1790 // TODO: FILE_FLAG_BACKUP_SEMANTICS_W
1791 // FILE_FLAG_POSIX_SEMANTICS_W are not supported
1792
1793 //TODO: FILE_SHARE_DELETE
1794 if((fuShare & (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W)) == 0 )
1795 openMode |= OPEN_SHARE_DENYREADWRITE;
1796 else
1797 if((fuShare & (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W)) == (FILE_SHARE_READ_W | FILE_SHARE_WRITE_W))
1798 openMode |= OPEN_SHARE_DENYNONE;
1799 else
1800 if(fuShare & FILE_SHARE_READ_W)
1801 openMode |= OPEN_SHARE_DENYWRITE;
1802 else
1803 if(fuShare & FILE_SHARE_WRITE_W)
1804 openMode |= OPEN_SHARE_DENYREAD;
1805
1806 if(fuAccess == (GENERIC_READ_W | GENERIC_WRITE_W))
1807 openMode |= OPEN_ACCESS_READWRITE;
1808 else
1809 if(fuAccess & GENERIC_READ_W)
1810 openMode |= OPEN_ACCESS_READONLY;
1811 else
1812 if(fuAccess & GENERIC_WRITE_W)
1813 openMode |= OPEN_ACCESS_WRITEONLY;
1814
1815 if (strstr(lpName,"\\\\."))
1816 {
1817 // If pipe is created on the local machine
1818 // we must delete string \\. because
1819 // in Windows named pipes scheme is a \\.\PIPE\pipename
1820 // but in OS/2 only \PIPE\pipename
1821 lpOS2Name = (LPSTR)lpName + 3;
1822 }
1823 else lpOS2Name = (LPSTR)lpName;
1824
1825 rc = DosOpen(lpOS2Name, &hPipe, &ulAction, 0, 0,
1826 openFlag, openMode, NULL);
1827
1828 if(rc == NO_ERROR) {
1829 dprintf(("Opening of existing named pipe succeeded"));
1830 SetLastError(ERROR_SUCCESS_W);
1831 return hPipe;
1832 }
1833
1834 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER_W));
1835 return -1; // INVALID_HANDLE_VALUE
1836}
1837
1838//******************************************************************************
1839//******************************************************************************
1840// TODO: implement lpOverlapped parameter!
1841BOOL OSLibDosConnectNamedPipe(DWORD hNamedPipe, LPOVERLAPPED lpOverlapped)
1842{
1843 DWORD rc;
1844
1845 rc=DosConnectNPipe(hNamedPipe);
1846 dprintf(("DosConnectNPipe rc=%d",rc));
1847
1848 if(rc == NO_ERROR) {
1849 SetLastError(ERROR_SUCCESS_W);
1850 return (TRUE);
1851 }
1852 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1853 return (FALSE);
1854}
1855
1856//******************************************************************************
1857//******************************************************************************
1858BOOL OSLibDosCallNamedPipe( LPCTSTR lpNamedPipeName,
1859 LPVOID lpInBuffer,
1860 DWORD nInBufferSize,
1861 LPVOID lpOutBuffer,
1862 DWORD nOutBufferSize,
1863 LPDWORD lpBytesRead,
1864 DWORD nTimeOut )
1865{
1866 LPSTR lpOS2Name;
1867 DWORD rc;
1868
1869 if (strstr(lpNamedPipeName,"\\\\."))
1870 {
1871 // If pipe is created on the local machine
1872 // we must delete string \\. because
1873 // in Windows named pipes scheme is a \\.\PIPE\pipename
1874 // but in OS/2 only \PIPE\pipename
1875 lpOS2Name = (LPSTR)lpNamedPipeName + 3;
1876 }
1877 else lpOS2Name = (LPSTR)lpNamedPipeName;
1878
1879 rc=DosCallNPipe(lpOS2Name,
1880 lpInBuffer,
1881 nInBufferSize,
1882 lpOutBuffer,
1883 nOutBufferSize,
1884 lpBytesRead,
1885 nTimeOut );
1886
1887
1888 if(rc == NO_ERROR) {
1889 SetLastError(ERROR_SUCCESS_W);
1890 return (TRUE);
1891 }
1892 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1893 return (FALSE);
1894}
1895
1896//******************************************************************************
1897//******************************************************************************
1898BOOL OSLibDosTransactNamedPipe( DWORD hNamedPipe,
1899 LPVOID lpInBuffer,
1900 DWORD nInBufferSize,
1901 LPVOID lpOutBuffer,
1902 DWORD nOutBufferSize,
1903 LPDWORD lpBytesRead,
1904 LPOVERLAPPED lpOverlapped)
1905{
1906 DWORD rc;
1907
1908 rc=DosTransactNPipe(hNamedPipe,
1909 lpOutBuffer,
1910 nOutBufferSize,
1911 lpInBuffer,
1912 nInBufferSize,
1913 lpBytesRead);
1914
1915 dprintf(("DosTransactNPipe returned rc=%d");)
1916 if(rc == NO_ERROR) {
1917 SetLastError(ERROR_SUCCESS_W);
1918 return (TRUE);
1919 }
1920 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1921 return (FALSE);
1922}
1923
1924//******************************************************************************
1925//******************************************************************************
1926BOOL OSLibDosPeekNamedPipe(DWORD hPipe,
1927 LPVOID lpvBuffer,
1928 DWORD cbBuffer,
1929 LPDWORD lpcbRead,
1930 LPDWORD lpcbAvail,
1931 LPDWORD lpcbMessage)
1932{
1933 DWORD rc;
1934 AVAILDATA availData ={0};
1935 ULONG ulState, ulRead, ulMessage;
1936 char buffer;
1937
1938 if(lpcbRead == NULL) {
1939 lpcbRead = &ulRead;
1940 }
1941 if(lpcbMessage == NULL) {
1942 lpcbMessage = &ulMessage;
1943 }
1944 if(lpvBuffer == NULL) {
1945 lpvBuffer = &buffer;
1946 cbBuffer = 0;
1947 }
1948
1949 rc = DosPeekNPipe(hPipe,lpvBuffer,cbBuffer,lpcbRead,&availData,&ulState);
1950
1951 dprintf(("DosPeekNPipe returned rc=%d",rc));
1952
1953 //OS/2 doesn't support DosPeekNPipe for unnamed pipes; win32 does
1954 if (rc == 1) {
1955 dprintf(("WARNING: Pretend broken pipe for PeekNamedPipe with unnamed pipe handle"));
1956 SetLastError(ERROR_BROKEN_PIPE_W);
1957 return FALSE;
1958 }
1959 if (rc == NO_ERROR)
1960 {
1961 if(lpcbAvail) {
1962 *lpcbAvail = availData.cbpipe;
1963 }
1964 if(lpcbMessage) {
1965 *lpcbMessage = availData.cbmessage;
1966 }
1967 SetLastError(ERROR_SUCCESS_W);
1968 return (TRUE);
1969 }
1970 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1971 return (FALSE);
1972}
1973//******************************************************************************
1974//******************************************************************************
1975BOOL OSLibDosDisconnectNamedPipe(DWORD hPipe)
1976{
1977 DWORD rc;
1978
1979 rc=DosDisConnectNPipe(hPipe);
1980
1981 dprintf(("DosDisConnectNPipe returned rc=%d",rc));
1982
1983 if(rc == NO_ERROR) {
1984 SetLastError(ERROR_SUCCESS_W);
1985 return (TRUE);
1986 }
1987 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
1988 return (FALSE);
1989}
1990//******************************************************************************
1991//******************************************************************************
1992BOOL OSLibDosWaitNamedPipe(LPCSTR lpszNamedPipeName,
1993 DWORD dwTimeout)
1994{
1995 LPSTR lpOS2Name;
1996 DWORD rc;
1997
1998 if (strstr(lpszNamedPipeName,"\\\\."))
1999 {
2000 // If pipe is created on the local machine
2001 // we must delete string \\. because
2002 // in Windows named pipes scheme is a \\.\PIPE\pipename
2003 // but in OS/2 only \PIPE\pipename
2004 lpOS2Name = (LPSTR)lpszNamedPipeName + 3;
2005 }
2006 else lpOS2Name = (LPSTR)lpszNamedPipeName;
2007
2008 rc=DosWaitNPipe(lpOS2Name,dwTimeout);
2009
2010 dprintf(("DosWaitNPipe returned rc=%d",rc));
2011
2012 if(rc == NO_ERROR) {
2013 SetLastError(ERROR_SUCCESS_W);
2014 return (TRUE);
2015 }
2016 SetLastError(error2WinError(rc,ERROR_PIPE_NOT_CONNECTED_W));
2017
2018 return (FALSE);
2019}
2020//******************************************************************************
2021//******************************************************************************
2022BOOL isRoot(CHAR* name)
2023{
2024 if (name[1] == ':')
2025 {
2026 //local name (x:\)
2027 return (name[2] == 0) || !strchr(&name[3],'\\');
2028 } else if (name[0] == '\\')
2029 {
2030 //UNC name (\\resource\drive\)
2031 CHAR *drive,*dir;
2032
2033 drive = strchr(&name[2],'\\');
2034 if (!drive) return FALSE;
2035 dir = strchr(&drive[1],'\\');
2036 if (!dir) return TRUE;
2037 return !strchr(&dir[1],'\\');
2038 } else return FALSE; //unknown
2039}
2040//******************************************************************************
2041//******************************************************************************
2042inline CHAR system2DOSCharacter(CHAR ch)
2043{
2044 switch(ch)
2045 {
2046 case ' ':
2047 case '.':
2048 case '~':
2049 return '_';
2050
2051 default:
2052 return toupper(ch);
2053 }
2054}
2055
2056// TODO: not finished nor correct!!!!
2057VOID long2ShortName(CHAR* longName, CHAR* shortName)
2058{
2059 // check for uplink / root: "." and ".."
2060 if (longName[0] == '.')
2061 {
2062 // if ((strcmp(longName,".") == 0) || (strcmp(longName,"..") == 0))
2063 if (longName[1] == 0) // "."
2064 {
2065 shortName[0] = '.';
2066 shortName[1] = 0;
2067 return;
2068 }
2069
2070 if (longName[1] == '.' && longName[2] == 0) // ".."
2071 {
2072 shortName[0] = '.';
2073 shortName[1] = '.';
2074 shortName[2] = 0;
2075 return;
2076 }
2077 }
2078 else
2079 // check for empty name
2080 if(longName[0] == 0)
2081 {
2082 shortName[0] = 0;
2083 return;
2084 }
2085
2086 INT x;
2087 CHAR *source = longName;
2088
2089 // Test if longName is 8:3 compliant and simply copy
2090 // the filename.
2091 BOOL flag83 = TRUE;
2092
2093 // verify forbidden characters
2094 for (x = 0;
2095 (x < 8) &&
2096 (flag83 == TRUE);
2097 x++)
2098 {
2099 switch (*source)
2100 {
2101 case '.': // a period will cause the loop to abort!
2102 x=1000;
2103 break;
2104
2105 case '/': case '?':
2106 case '*': case ':':
2107 case '\\': case '"':
2108 case ' ':
2109 flag83 = FALSE;
2110 break;
2111 default:
2112 source++;
2113 break;
2114 }
2115 }
2116
2117 // verify we're on a period now
2118 if (flag83 == TRUE)
2119 if (*source != '.')
2120 flag83 = FALSE;
2121 else source++;
2122
2123 // verify extension
2124 if (flag83 == TRUE)
2125 for (INT y = 0;
2126 (y < 3) && (flag83 == TRUE);
2127 y++)
2128 {
2129 switch (*source)
2130 {
2131 case '/': case '?':
2132 case '*': case ':':
2133 case '\\': case '"':
2134 case ' ': case '.':
2135 flag83 = FALSE;
2136 break;
2137 }
2138 source++;
2139 }
2140
2141 // verify we're at the end of the string now
2142 if (flag83 == TRUE)
2143 if (*source != 0)
2144 flag83 = FALSE;
2145
2146 // OK, done
2147 if (flag83 == TRUE)
2148 {
2149 // we might not alter any character here, since
2150 // an app opening a specific file with an 8:3 "alias",
2151 // would surely fail.
2152 strcpy(shortName, longName);
2153
2154 return; // Done
2155 }
2156
2157
2158 // @@@PH
2159 shortName[0] = 0; // this function is disabled anyway ...
2160 return;
2161
2162 CHAR *dest = shortName;
2163 CHAR *ext = strrchr(longName,'.');
2164
2165 //CB: quick and dirty, real FILE~12.EXT is too slow
2166 //PH: We'd have to count the number of non-8:3-compliant files
2167 // within a directory. Or simpler: the number of files within
2168 // the current directory.
2169
2170 //8 character file name
2171 for (x = 0;x < 8;x++)
2172 {
2173 if ((source == ext) || (source[0] == 0)) break;
2174 dest[0] = system2DOSCharacter(source[0]);
2175 source++;
2176 dest++;
2177 }
2178
2179 if (source[0] == 0)
2180 {
2181 dest[0] = 0;
2182 return;
2183 }
2184
2185 if (source != ext)
2186 {
2187 //longName > 8 characters, insert ~1
2188 shortName[6] = '~';
2189 shortName[7] = '1';
2190 }
2191
2192 if (ext)
2193 {
2194 //add extension, 3 characters
2195 dest[0] = ext[0];
2196 dest++;
2197 ext++;
2198 for (x = 0;x < 3;x++)
2199 {
2200 if (ext[0] == 0) break;
2201 dest[0] = system2DOSCharacter(ext[0]);
2202 ext++;
2203 dest++;
2204 }
2205 }
2206 dest[0] = 0;
2207}
2208//******************************************************************************
2209//******************************************************************************
2210VOID translateFileResults(FILESTATUS3 *pResult,LPWIN32_FIND_DATAA pFind,CHAR* achName)
2211{
2212 CHAR* name;
2213
2214 pFind->dwReserved0 = pFind->dwReserved1 = 0;
2215 pFind->dwFileAttributes = pm2WinFileAttributes(pResult->attrFile);
2216
2217 pmDateTimeToFileTime(&pResult->fdateCreation,&pResult->ftimeCreation,&pFind->ftCreationTime);
2218 pmDateTimeToFileTime(&pResult->fdateLastAccess,&pResult->ftimeLastAccess,&pFind->ftLastAccessTime);
2219 pmDateTimeToFileTime(&pResult->fdateLastWrite,&pResult->ftimeLastWrite,&pFind->ftLastWriteTime);
2220
2221 pFind->nFileSizeHigh = 0; //CB: fixme
2222 pFind->nFileSizeLow = pResult->cbFile;
2223 name = strrchr(achName,'\\');
2224 if (name)
2225 {
2226 name++;
2227// strcpy(pFind->cFileName,name);
2228 OemToCharA( name, pFind->cFileName );
2229 }
2230 else
2231 pFind->cFileName[0] = 0;
2232
2233 long2ShortName(pFind->cFileName,pFind->cAlternateFileName);
2234}
2235
2236
2237VOID translateFindResults(FILEFINDBUF3 *pResult,LPWIN32_FIND_DATAA pFind)
2238{
2239 pFind->dwFileAttributes = pm2WinFileAttributes(pResult->attrFile);
2240 pFind->dwReserved0 = pFind->dwReserved1 = 0;
2241
2242 pmDateTimeToFileTime(&pResult->fdateCreation,&pResult->ftimeCreation,&pFind->ftCreationTime);
2243 pmDateTimeToFileTime(&pResult->fdateLastAccess,&pResult->ftimeLastAccess,&pFind->ftLastAccessTime);
2244 pmDateTimeToFileTime(&pResult->fdateLastWrite,&pResult->ftimeLastWrite,&pFind->ftLastWriteTime);
2245
2246 pFind->nFileSizeHigh = 0; //CB: fixme
2247 pFind->nFileSizeLow = pResult->cbFile;
2248// strcpy(pFind->cFileName,pResult->achName);
2249 OemToCharA( pResult->achName, pFind->cFileName );
2250 long2ShortName(pFind->cFileName,pFind->cAlternateFileName);
2251}
2252//******************************************************************************
2253//******************************************************************************
2254DWORD OSLibDosFindFirst(LPCSTR lpFileName,WIN32_FIND_DATAA* lpFindFileData)
2255{
2256 HDIR hDir = -1;
2257 ULONG attrs;
2258 FILEFINDBUF3 result;
2259 ULONG searchCount = 1;
2260
2261 attrs = FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED;
2262 result.achName[0] = 0;
2263
2264 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS_W);
2265 char lOemFileName[260];
2266
2267 CharToOemA(ODINHelperStripUNC((char*)lpFileName), lOemFileName);
2268
2269 APIRET rc = DosFindFirst((PSZ)lOemFileName,&hDir,attrs,&result,sizeof(result),&searchCount,FIL_STANDARD);
2270
2271 //check root: skip "." and ".." (HPFS, not on FAT)
2272 //check in OSLibDosFindNext not necessary: "." and ".." are the first two entries
2273 if ((rc == 0) && isRoot((LPSTR)ODINHelperStripUNC((char*)lpFileName)))
2274 {
2275 while ((strcmp(result.achName,".") == 0) ||
2276 (strcmp(result.achName,"..") == 0))
2277 {
2278 result.achName[0] = 0;
2279 searchCount = 1;
2280 APIRET rc = DosFindNext(hDir,&result,sizeof(result),&searchCount);
2281 if (rc)
2282 {
2283 DosFindClose(hDir);
2284 SetLastError(error2WinError(rc));
2285
2286 SetErrorMode(oldmode);
2287 return INVALID_HANDLE_VALUE_W;
2288 }
2289 }
2290 }
2291
2292 // enable i/o kernel exceptions again
2293 SetErrorMode(oldmode);
2294
2295 if(rc)
2296 {
2297 DosFindClose(hDir);
2298
2299 //Windows returns ERROR_FILE_NOT_FOUND if the file/directory is not present
2300 if(rc == ERROR_NO_MORE_FILES || rc == ERROR_PATH_NOT_FOUND) {
2301 SetLastError(ERROR_FILE_NOT_FOUND_W);
2302 }
2303 else SetLastError(error2WinError(rc));
2304 return INVALID_HANDLE_VALUE_W;
2305 }
2306 translateFindResults(&result,lpFindFileData);
2307 SetLastError(ERROR_SUCCESS_W);
2308 return hDir;
2309}
2310//******************************************************************************
2311// NOTE: returns "." and ".." in root
2312//******************************************************************************
2313DWORD OSLibDosFindFirstMulti(LPCSTR lpFileName,WIN32_FIND_DATAA *lpFindFileData,DWORD *count)
2314{
2315 HDIR hDir = -1;
2316 ULONG attrs;
2317 FILEFINDBUF3 *result,*data;
2318 ULONG searchCount = *count;
2319
2320 attrs = FILE_READONLY | FILE_HIDDEN | FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED;
2321 result = (FILEFINDBUF3*)malloc(searchCount*sizeof(FILEFINDBUF3));
2322
2323 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS_W);
2324 char lOemFileName[260];
2325
2326 CharToOemA(ODINHelperStripUNC((char*)lpFileName), lOemFileName);
2327 APIRET rc = DosFindFirst((PSZ)lOemFileName,&hDir,attrs,result,searchCount*sizeof(FILEFINDBUF3),&searchCount,FIL_STANDARD);
2328 SetErrorMode(oldmode);
2329 if (rc)
2330 {
2331 free(result);
2332 *count = 0;
2333 SetLastError(error2WinError(rc));
2334
2335 return INVALID_HANDLE_VALUE_W;
2336 }
2337
2338 data = result;
2339 for (int x = 0;x < searchCount;x++)
2340 {
2341 translateFindResults(data,&lpFindFileData[x]);
2342 data = (FILEFINDBUF3*)(((DWORD)data)+data->oNextEntryOffset);
2343 }
2344 free(result);
2345 *count = searchCount;
2346
2347 SetLastError(ERROR_SUCCESS_W);
2348 return hDir;
2349}
2350//******************************************************************************
2351//******************************************************************************
2352BOOL OSLibDosFindNext(DWORD hFindFile,WIN32_FIND_DATAA *lpFindFileData)
2353{
2354 FILEFINDBUF3 result;
2355 ULONG searchCount = 1;
2356
2357 APIRET rc = DosFindNext((HDIR)hFindFile,&result,sizeof(result),&searchCount);
2358 if (rc)
2359 {
2360 SetLastError(error2WinError(rc));
2361
2362 return FALSE;
2363 }
2364
2365 translateFindResults(&result,lpFindFileData);
2366 SetLastError(ERROR_SUCCESS_W);
2367 return TRUE;
2368}
2369//******************************************************************************
2370//******************************************************************************
2371BOOL OSLibDosFindNextMulti(DWORD hFindFile,WIN32_FIND_DATAA *lpFindFileData,DWORD *count)
2372{
2373 FILEFINDBUF3 *result,*data;
2374 ULONG searchCount = *count;
2375
2376 result = (FILEFINDBUF3*)malloc(searchCount*sizeof(FILEFINDBUF3));
2377 APIRET rc = DosFindNext((HDIR)hFindFile,result,searchCount*sizeof(FILEFINDBUF3),&searchCount);
2378 if (rc)
2379 {
2380 free(result);
2381 *count = 0;
2382 SetLastError(error2WinError(rc));
2383
2384 return FALSE;
2385 }
2386
2387 data = result;
2388 for (int x = 0;x < searchCount;x++)
2389 {
2390 translateFindResults(data,&lpFindFileData[x]);
2391 data = (FILEFINDBUF3*)(((DWORD)data)+data->oNextEntryOffset);
2392 }
2393 free(result);
2394 *count = searchCount;
2395
2396 SetLastError(ERROR_SUCCESS_W);
2397 return TRUE;
2398}
2399//******************************************************************************
2400//******************************************************************************
2401BOOL OSLibDosFindClose(DWORD hFindFile)
2402{
2403 APIRET rc = DosFindClose((HDIR)hFindFile);
2404 if (rc)
2405 {
2406 SetLastError(error2WinError(rc));
2407 return FALSE;
2408 }
2409
2410 SetLastError(ERROR_SUCCESS_W);
2411 return TRUE;
2412}
2413//******************************************************************************
2414//******************************************************************************
2415DWORD OSLibGetFileAttributes(LPSTR lpFileName)
2416{
2417 FILESTATUS3 statusBuf;
2418 char lOemFileName[CCHMAXPATH];
2419 char *lpszBackslash, *lpszColon;
2420 APIRET rc;
2421
2422//testestest
2423 if(strlen(lpFileName) > CCHMAXPATH) DebugInt3();
2424//testestset
2425
2426 //Convert file name from Windows to OS/2 codepage
2427 CharToOemA(ODINHelperStripUNC(lpFileName), lOemFileName);
2428 lpszBackslash = CharPrevA(lOemFileName, lOemFileName + strlen(lOemFileName));
2429 if(lpszBackslash)
2430 {
2431 if(*lpszBackslash == '\\')
2432 {
2433 lpszColon = CharPrevA(lOemFileName, lpszBackslash);
2434 if(lpszColon && *lpszColon != ':')
2435 {//only rootdir is allowed to have terminating backslash
2436 *lpszBackslash = 0;
2437 }
2438 }
2439 else
2440 if(*lpszBackslash == ':')
2441 {//root dir must end with backslash
2442 strcat(lOemFileName, "\\");
2443 }
2444 }
2445
2446 rc = DosQueryPathInfo(lOemFileName, FIL_STANDARD, &statusBuf, sizeof(statusBuf));
2447 if(rc == ERROR_TOO_MANY_OPEN_FILES)
2448 {
2449 LONG reqCount = 2;
2450 ULONG maxFiles;
2451
2452 if(DosSetRelMaxFH(&reqCount, &maxFiles) == NO_ERROR)
2453 rc = DosQueryPathInfo(lOemFileName, FIL_STANDARD, &statusBuf, sizeof(statusBuf));
2454 }
2455
2456 if(rc == NO_ERROR)
2457 {
2458 DWORD status = 0;
2459 if(!(statusBuf.attrFile & NOT_NORMAL))
2460 status |= FILE_ATTRIBUTE_NORMAL_W;
2461 if(statusBuf.attrFile & FILE_READONLY)
2462 status |= FILE_ATTRIBUTE_READONLY_W;
2463 if(statusBuf.attrFile & FILE_HIDDEN)
2464 status |= FILE_ATTRIBUTE_HIDDEN_W;
2465 if(statusBuf.attrFile & FILE_SYSTEM)
2466 status |= FILE_ATTRIBUTE_SYSTEM_W;
2467 if(statusBuf.attrFile & FILE_DIRECTORY)
2468 status |= FILE_ATTRIBUTE_DIRECTORY_W;
2469 if(statusBuf.attrFile & FILE_ARCHIVED)
2470 status |= FILE_ATTRIBUTE_ARCHIVE_W;
2471
2472 SetLastError(ERROR_SUCCESS_W);
2473 return status;
2474 }
2475 SetLastError(error2WinError(rc));
2476 return -1;
2477}
2478//******************************************************************************
2479#define FSATTACH_SIZE 256
2480//******************************************************************************
2481DWORD OSLibDosQueryVolumeFS(int drive, LPSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize)
2482{
2483 PFSQBUFFER2 fsinfo = (PFSQBUFFER2) alloca(FSATTACH_SIZE);
2484 ULONG cb = FSATTACH_SIZE;
2485 char drv[3] = "A:";
2486 char *fsname;
2487 APIRET rc;
2488
2489 if(lpFileSystemNameBuffer == NULL) {
2490 DebugInt3();
2491 return ERROR_INVALID_PARAMETER_W;
2492 }
2493 drv[0] = (char)('A' + drive - 1);
2494
2495 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS_W);
2496 rc = DosQueryFSAttach(drv, 1, FSAIL_QUERYNAME, fsinfo, &cb);
2497 SetErrorMode(oldmode);
2498
2499 switch(rc) {
2500 case ERROR_INVALID_DRIVE:
2501 return ERROR_INVALID_DRIVE_W;
2502 case ERROR_NO_VOLUME_LABEL:
2503 return ERROR_NO_VOLUME_LABEL_W;
2504 case NO_ERROR:
2505 break;
2506 default:
2507 return ERROR_NOT_ENOUGH_MEMORY; //whatever
2508 }
2509
2510 fsname = (char *)&fsinfo->szName[0] + fsinfo->cbName + 1;
2511
2512 /* @@@PH 2000/08/10 CMD.EXE querys with nFileSystemNameSize == 0
2513 * however does NOT expect to receive an error.
2514 */
2515 strncpy(lpFileSystemNameBuffer,
2516 fsname,
2517 nFileSystemNameSize);
2518 /*
2519 if(strlen(fsname) < nFileSystemNameSize) {
2520 strcpy(lpFileSystemNameBuffer, fsname);
2521 }
2522 else return ERROR_BUFFER_OVERFLOW_W;
2523 */
2524 return ERROR_SUCCESS_W;
2525}
2526//******************************************************************************
2527typedef struct _FSINFOBUF
2528{
2529 ULONG ulVolser; /* Volume serial number */
2530 VOLUMELABEL vol; /* Volume lable */
2531} FSINFOBUF;
2532//******************************************************************************
2533DWORD OSLibDosQueryVolumeSerialAndName(int drive, LPDWORD lpVolumeSerialNumber,
2534 LPSTR lpVolumeNameBuffer, DWORD nVolumeNameSize)
2535{
2536 FSINFOBUF fsi;
2537 APIRET rc;
2538
2539 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS_W);
2540 rc = DosQueryFSInfo(drive, FSIL_VOLSER, &fsi, sizeof(fsi));
2541 SetErrorMode(oldmode);
2542
2543 switch(rc) {
2544 case ERROR_INVALID_DRIVE:
2545 return ERROR_INVALID_DRIVE_W;
2546 case ERROR_NO_VOLUME_LABEL:
2547 return ERROR_NO_VOLUME_LABEL_W;
2548 case NO_ERROR:
2549 break;
2550 default:
2551 return ERROR_NOT_ENOUGH_MEMORY; //whatever
2552 }
2553
2554 if(lpVolumeSerialNumber) {
2555 *lpVolumeSerialNumber = fsi.ulVolser;
2556 }
2557 if(lpVolumeNameBuffer)
2558 {
2559 if(nVolumeNameSize > fsi.vol.cch) {
2560 strcpy(lpVolumeNameBuffer, (PCHAR)fsi.vol.szVolLabel);
2561 }
2562 else return ERROR_BUFFER_OVERFLOW_W;
2563 }
2564
2565 return ERROR_SUCCESS_W;
2566}
2567//******************************************************************************
2568//******************************************************************************
2569BOOL OSLibGetDiskFreeSpace(LPSTR lpRootPathName, LPDWORD lpSectorsPerCluster,
2570 LPDWORD lpBytesPerSector, LPDWORD lpNumberOfFreeClusters,
2571 LPDWORD lpTotalNumberOfClusters)
2572{
2573 ULONG diskNum;
2574 FSALLOCATE fsAlloc;
2575 APIRET rc;
2576
2577 if(lpRootPathName == 0)
2578 diskNum = 0;
2579 else
2580 if('A' <= *lpRootPathName && *lpRootPathName <= 'Z' )
2581 diskNum = *lpRootPathName - 'A' + 1;
2582 else
2583 if('a' <= *lpRootPathName && *lpRootPathName <= 'z' )
2584 diskNum = *lpRootPathName - 'a' + 1;
2585 else
2586 diskNum = 0;
2587
2588 ULONG oldmode = SetErrorMode(SEM_FAILCRITICALERRORS_W);
2589 rc = DosQueryFSInfo(diskNum, FSIL_ALLOC, &fsAlloc, sizeof(fsAlloc));
2590 SetErrorMode(oldmode);
2591
2592 if(rc == 0)
2593 {
2594 *lpSectorsPerCluster = fsAlloc.cSectorUnit;
2595 *lpBytesPerSector = fsAlloc.cbSector;
2596 *lpNumberOfFreeClusters = fsAlloc.cUnitAvail;
2597 *lpTotalNumberOfClusters = fsAlloc.cUnit;
2598 SetLastError(ERROR_SUCCESS_W);
2599 return TRUE;
2600 }
2601 SetLastError(error2WinError(rc));
2602 return FALSE;
2603}
2604//******************************************************************************
2605//******************************************************************************
2606BOOL OSLibDosGetDiskGeometry(HANDLE hDisk, DWORD cDisk, PVOID pdiskgeom)
2607{
2608 PDISK_GEOMETRY pGeom = (PDISK_GEOMETRY)pdiskgeom;
2609 BYTE param[2] = {0, 0};
2610 ULONG parsize = 2;
2611 BIOSPARAMETERBLOCK bpb;
2612 ULONG datasize = sizeof(bpb);
2613 APIRET rc;
2614
2615 dprintf(("OSLibDosGetDiskGeometry %x %d %x", hDisk, cDisk, pdiskgeom));
2616 param[1] = cDisk - 'A';
2617 rc = DosDevIOCtl((hDisk) ? hDisk : -1, IOCTL_DISK, DSK_GETDEVICEPARAMS, param, 2, &parsize, &bpb, sizeof(bpb), &datasize);
2618 if(rc == 0)
2619 {
2620 pGeom->SectorsPerTrack = bpb.usSectorsPerTrack;
2621 pGeom->BytesPerSector = bpb.usBytesPerSector;
2622 pGeom->TracksPerCylinder = 80; //TODO:!!!!!
2623 pGeom->Cylinders.u.LowPart = bpb.cCylinders;
2624 pGeom->Cylinders.u.HighPart = 0;
2625 switch(bpb.bDeviceType) {
2626 case DEVTYPE_48TPI:
2627 pGeom->MediaType = F5_360_512; //?????
2628 break;
2629 case DEVTYPE_96TPI:
2630 pGeom->MediaType = F5_1Pt2_512; //?????
2631 break;
2632 case DEVTYPE_35:
2633 pGeom->MediaType = F3_720_512;
2634 break;
2635 case DEVTYPE_8SD:
2636 case DEVTYPE_8DD:
2637 pGeom->MediaType = RemovableMedia;
2638 break;
2639 case DEVTYPE_FIXED:
2640 pGeom->MediaType = FixedMedia;
2641 break;
2642 case DEVTYPE_TAPE:
2643 pGeom->MediaType = RemovableMedia;
2644 break;
2645 case DEVTYPE_UNKNOWN: //others, include 1.44 3.5 inch disk drive
2646 pGeom->MediaType = F3_1Pt44_512;
2647 break;
2648 case 8: //RW optical disk
2649 pGeom->MediaType = RemovableMedia;
2650 break;
2651 case 9: //2.88 3.5 inch disk
2652 pGeom->MediaType = F3_2Pt88_512;
2653 break;
2654 }
2655 SetLastError(ERROR_SUCCESS_W);
2656 return TRUE;
2657 }
2658 dprintf(("OSLibDosGetDiskGeometry: error %d -> %d", rc, error2WinError(rc)));
2659 SetLastError(error2WinError(rc));
2660 return FALSE;
2661}
2662//******************************************************************************
2663
2664#define CDType 0x8000
2665#define FloppyType 0x4000
2666#define LanType 0x2000
2667#define LogicalType 0x1000
2668#define VDISKType 0x0800
2669#define OpticalType 0x0400
2670#define NonRemovable 0x01
2671
2672#define FirstDrive 0
2673#define B_Drive_0_Based 1
2674#define Base_1_offset 1
2675#define Binary_to_Printable 0x41
2676#define LastDrive 26
2677#define OpticalSectorsPerCluster 4
2678
2679#define DisketteCylinders 80
2680
2681
2682
2683/**
2684 * Determin the type of a specific drive or the current drive.
2685 *
2686 * @returns DRIVE_UNKNOWN
2687 * DRIVE_NO_ROOT_DIR
2688 * DRIVE_CANNOTDETERMINE
2689 * DRIVE_DOESNOTEXIST
2690 * DRIVE_REMOVABLE
2691 * DRIVE_FIXED
2692 * DRIVE_REMOTE
2693 * DRIVE_CDROM
2694 * DRIVE_RAMDISK
2695 *
2696 * @param ulDrive Index of the drive which type we query.
2697 *
2698 * @status completely implemented and tested
2699 * @author Vitali Pelenyov <sunlover@anduin.net>
2700 * @author bird
2701 */
2702ULONG OSLibGetDriveType(ULONG ulDrive)
2703{
2704 ULONG cbParm;
2705 ULONG cbData;
2706 ULONG ulDriveNum = 0;
2707 ULONG ulDriveMap = 0;
2708 APIRET rc;
2709 ULONG ulDriveType;
2710
2711
2712 /*
2713 * Check if drive is present in the logical drive mask,
2714 */
2715 if ( DosQueryCurrentDisk(&ulDriveNum, &ulDriveMap)
2716 || !(ulDriveMap & (1 << ulDrive))
2717 )
2718 return DRIVE_DOESNOTEXIST_W;
2719
2720
2721 /*
2722 * Optimize floppy queries for A: and B:.
2723 * (These aren't currently a subject of change.)
2724 */
2725 static ULONG ulFloppyMask = 0;
2726 if (ulFloppyMask & (1 << ulDrive))
2727 return DRIVE_REMOVABLE_W;
2728
2729 /*
2730 * Optimize for CDROM requests.
2731 * (These aren't currently a subject of change.)
2732 */
2733 static ULONG ulCDROMMask = 0;
2734 if (ulCDROMMask & (1 << ulDrive))
2735 return DRIVE_CDROM_W;
2736
2737 /*
2738 * Check for CD drives
2739 * We don't have to this everytime. I mean, the os2cdrom.dmd is
2740 * exactly very dynamic when it comes to this info.
2741 */
2742 if (cdDrvLtr.drive_count == 0xffff)
2743 {
2744 HFILE hCDRom2;
2745 ULONG ulAction = 0;
2746
2747 if (DosOpen("\\DEV\\CD-ROM2$", &hCDRom2, &ulAction, 0,
2748 FILE_NORMAL, OPEN_ACTION_OPEN_IF_EXISTS,
2749 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY | OPEN_FLAGS_NOINHERIT, NULL)
2750 == NO_ERROR)
2751 {
2752 cbData = sizeof(cdDrvLtr);
2753 rc = DosDevIOCtl(hCDRom2,
2754 IOC_CDROM_2,
2755 IOCD_RETURN_DRIVE_LETTER,
2756 NULL, 0, NULL,
2757 (PVOID)&cdDrvLtr, sizeof(cdDrvLtr), &cbData);
2758 DosClose(hCDRom2);
2759 }
2760 else
2761 cdDrvLtr.drive_count = 0;
2762 }
2763
2764
2765 /*
2766 * Is the drive present?? Lets the the BPB to check this.
2767 * this should be a pretty speedy call if I'm not much mistaken.
2768 */
2769 BIOSPARAMETERBLOCK bpb = {0};
2770 DSKREQ DskReq;
2771 DskReq.Infotype = 0;
2772 DskReq.DriveUnit = (UCHAR)ulDrive;
2773 cbParm = sizeof(DskReq);
2774 cbData = sizeof(bpb);
2775 if (DosDevIOCtl(-1, IOCTL_DISK, DSK_GETDEVICEPARAMS,
2776 (PVOID)&DskReq, sizeof(DskReq), &cbParm,
2777 (PVOID)&bpb, sizeof(BIOSPARAMETERBLOCK), &cbData)
2778 == NO_ERROR)
2779 {
2780 if (bpb.bDeviceType == 0 && bpb.fsDeviceAttr == 0)
2781 bpb.fsDeviceAttr = LanType; // fix for LAN type drives
2782 }
2783 else
2784 bpb.fsDeviceAttr = LanType; //could be a LAN drive - could it??
2785
2786
2787 /*
2788 * This is a CDROM/DVD drive
2789 *
2790 * Fix: When the cdrom is not last drive letter that
2791 * sometimes reports wrong index, have to check
2792 * that device type can be a CDROM one.
2793 */
2794 if ( cdDrvLtr.drive_count > 0
2795 && (bpb.bDeviceType == DEVTYPE_UNKNOWN || bpb.bDeviceType == DEVTYPE_OPTICAL) // Other or RW optical
2796 && ulDrive >= cdDrvLtr.first_drive_number
2797 && ulDrive < cdDrvLtr.first_drive_number + cdDrvLtr.drive_count
2798 )
2799 bpb.fsDeviceAttr |= CDType;
2800
2801
2802 if (bpb.bDeviceType || bpb.fsDeviceAttr == LanType)
2803 {
2804 if ((bpb.fsDeviceAttr & (CDType | NonRemovable)) == 0)
2805 { // if the device is removable and NOT a CD
2806 CHAR szDevName[4] = "A:";
2807 PFSQBUFFER2 pfsqbuf2;
2808
2809 szDevName[0] += ulDrive;
2810 cbData = sizeof(PFSQBUFFER2) + 3 * CCHMAXPATH;
2811 pfsqbuf2 = (PFSQBUFFER2)malloc(cbData);
2812 DosError(FERR_DISABLEEXCEPTION | FERR_DISABLEHARDERR); // disable error popups
2813 rc = DosQueryFSAttach(&szDevName[0], 0L, FSAIL_QUERYNAME, pfsqbuf2, &cbData);
2814 if (rc == NO_ERROR)
2815 {
2816 if (pfsqbuf2->iType == FSAT_REMOTEDRV)
2817 bpb.fsDeviceAttr |= LanType;
2818 else if (pfsqbuf2->iType == FSAT_LOCALDRV)
2819 {
2820 PSZ pszFSName = (PSZ)pfsqbuf2->szName + pfsqbuf2->cbName + 1;
2821 if (!strcmp(pszFSName, "FAT"))
2822 {
2823 // device is a removable FAT drive, so it MUST be diskette
2824 // as Optical has another name as does LAN and SRVIFS
2825 if (bpb.bSectorsPerCluster != OpticalSectorsPerCluster)
2826 bpb.fsDeviceAttr |= FloppyType;
2827 else
2828 bpb.fsDeviceAttr |= OpticalType;
2829 }
2830 /*
2831 * CDROM detection fix
2832 */
2833 else
2834 {
2835 // device is removable non-FAT, maybe it is CD?
2836 if ( bpb.bDeviceType == DEVTYPE_UNKNOWN
2837 && bpb.bMedia == 5
2838 && bpb.usBytesPerSector > 512
2839 )
2840 bpb.fsDeviceAttr |= CDType;
2841 }
2842 // CDROM detection fix
2843 }
2844 }
2845 else // must be no media or audio only (for CDs at least)
2846 {
2847 if (bpb.cCylinders <= DisketteCylinders) // floppies will always be 80
2848 {
2849 // or less cylinders
2850 if (bpb.bSectorsPerCluster != OpticalSectorsPerCluster)
2851 bpb.fsDeviceAttr |= FloppyType;
2852 else
2853 bpb.fsDeviceAttr |= OpticalType;
2854 }
2855 }
2856
2857 //Enable error popups again
2858 DosError(FERR_ENABLEEXCEPTION | FERR_ENABLEHARDERR);
2859
2860 free(pfsqbuf2);
2861 }
2862 else
2863 {// non removable or CD type. maybe RAM disk
2864 if (!(bpb.fsDeviceAttr & CDType)) // if NOT CD
2865 {
2866 if (bpb.cFATs == 1) // is there only one FAT?
2867 bpb.fsDeviceAttr |= VDISKType; // -> RAM disk
2868 }
2869 }
2870 }
2871
2872
2873 /*
2874 * Determin return value.
2875 */
2876 if (bpb.fsDeviceAttr & FloppyType)
2877 {
2878 ulDriveType = DRIVE_REMOVABLE_W;
2879 /* update floppy cache if A or B */
2880 if (ulDrive <= 1)
2881 ulFloppyMask |= 1 << ulDrive;
2882 }
2883 else if (bpb.fsDeviceAttr & CDType)
2884 {
2885 ulDriveType = DRIVE_CDROM_W;
2886 /* update cdrom cache */
2887 ulCDROMMask |= 1 << ulDrive;
2888 }
2889 else if (bpb.fsDeviceAttr & LanType)
2890 ulDriveType = DRIVE_REMOTE_W;
2891 else if (bpb.fsDeviceAttr & VDISKType)
2892 ulDriveType = DRIVE_RAMDISK_W;
2893 else if (bpb.fsDeviceAttr & OpticalType || bpb.bDeviceType == DEVTYPE_OPTICAL)
2894 ulDriveType = DRIVE_FIXED_W;
2895 else if (bpb.bDeviceType == DEVTYPE_FIXED)
2896 ulDriveType = DRIVE_FIXED_W;
2897 else
2898 ulDriveType = DRIVE_UNKNOWN_W;
2899
2900 return ulDriveType;
2901}
2902//******************************************************************************
2903//Returns bit map where with the mapping of the logical drives
2904//******************************************************************************
2905ULONG OSLibGetLogicalDrives()
2906{
2907 ULONG ulDriveNum = 0; /* Drive number (A=1, B=2, C=3, ...) */
2908 ULONG ulDriveMap = 0; /* Mapping of valid drives */
2909 APIRET rc;
2910
2911 rc = DosQueryCurrentDisk(&ulDriveNum, &ulDriveMap);
2912 if(rc) {
2913 DebugInt3();
2914 SetLastError(error2WinError(rc));
2915 return 0;
2916 }
2917 return ulDriveMap;
2918}
2919//******************************************************************************
2920//******************************************************************************
2921ULONG OSLibDosQueryCurrentDisk()
2922
2923{
2924 ULONG ulDriveNum = 0; /* Drive number (A=1, B=2, C=3, ...) */
2925 ULONG ulDriveMap = 0; /* Mapping of valid drives */
2926 APIRET rc;
2927
2928 rc = DosQueryCurrentDisk(&ulDriveNum, &ulDriveMap);
2929 if(rc) {
2930 DebugInt3();
2931 SetLastError(error2WinError(rc));
2932 return 0;
2933 }
2934 return ulDriveNum;
2935}
2936//******************************************************************************
2937//******************************************************************************
2938BOOL OSLibDosCreatePipe(PHANDLE phfRead,
2939 PHANDLE phfWrite,
2940 LPSECURITY_ATTRIBUTES lpsa,
2941 DWORD dwSize)
2942{
2943 APIRET rc;
2944
2945 dprintf(("DosCreatePipe(%08xh,%08xh,%08xh)\n",
2946 phfRead,
2947 phfWrite,
2948 dwSize));
2949
2950 // select default buffer size
2951 if (dwSize == 0)
2952 dwSize = 4096;
2953
2954 rc = DosCreatePipe(phfRead,
2955 phfWrite,
2956 dwSize);
2957 dprintf(("DosCreatePipe rc=%d",rc));
2958 if (rc)
2959 {
2960 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER_W));
2961 return -1; // INVALID_HANDLE_VALUE
2962 }
2963 SetLastError(ERROR_SUCCESS_W);
2964 return NO_ERROR;
2965}
2966//******************************************************************************
2967//******************************************************************************
2968DWORD SYSTEM OSLibDosDevIOCtl( DWORD hFile, DWORD dwCat, DWORD dwFunc,
2969 PVOID pParm, DWORD dwParmMaxLen, DWORD *pdwParmLen,
2970 PVOID pData, DWORD dwDataMaxLen, DWORD *pdwDataLen)
2971{
2972 APIRET rc;
2973 PVOID pTiledParm = pParm;
2974 BOOL flagTiledParm = FALSE;
2975 PVOID pTiledData = pData;
2976 BOOL flagTiledData = FALSE;
2977
2978#if 1
2979 /*
2980 * Quick and Dirty Fix!
2981 * TO BE REMOVED!
2982 *
2983 * On some VPC installation without CDROM we seem to
2984 * use a concidrable amount of time during Win2k shutdown.
2985 * No idea why, but it has to do with CDROM we think.
2986 *
2987 * So, let's just fail all IOCtls to CD01 if there aren't any
2988 * CDROMs in the system.
2989 *
2990 */
2991
2992 /*
2993 * Check for CD drives
2994 * We don't have to this everytime. I mean, the os2cdrom.dmd is
2995 * exactly very dynamic when it comes to this info.
2996 */
2997 if (cdDrvLtr.drive_count == 0xffff)
2998 {
2999 HFILE hCDRom2;
3000 ULONG ulAction = 0;
3001
3002 if (DosOpen("\\DEV\\CD-ROM2$", &hCDRom2, &ulAction, 0,
3003 FILE_NORMAL, OPEN_ACTION_OPEN_IF_EXISTS,
3004 OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY | OPEN_FLAGS_NOINHERIT, NULL)
3005 == NO_ERROR)
3006 {
3007 ULONG cbData = sizeof(cdDrvLtr);
3008 rc = DosDevIOCtl(hCDRom2,
3009 IOC_CDROM_2,
3010 IOCD_RETURN_DRIVE_LETTER,
3011 NULL, 0, NULL,
3012 (PVOID)&cdDrvLtr, sizeof(cdDrvLtr), &cbData);
3013 DosClose(hCDRom2);
3014 }
3015 else
3016 cdDrvLtr.drive_count = 0;
3017 }
3018
3019 if ( cdDrvLtr.drive_count == 0
3020 && (dwCat == IOCTL_CDROMDISK
3021 || (dwCat == IOCTL_CDROMAUDIO
3022 && dwParmMaxLen >= 4 && strncmp((char*)pParm, "CD01", 4))
3023 )
3024 )
3025 {
3026 /* just return some error code */
3027 return ERROR_BAD_COMMAND;
3028 }
3029
3030#endif
3031
3032#define MEM_TILED_CEILING 0x1fffffff
3033
3034 // bounce buffer support
3035 // make sure no parameter or data buffer can pass the tiled memory region
3036 // barrier (usually 512MB). OS/2 kernel does not correctly translate these
3037 // addresses to a 16:16 address used in device driver land. In fact,
3038 // DosDevIOCtl is not a high memory enabled API!
3039
3040 if (pTiledParm && (((DWORD)pTiledParm + max(dwParmMaxLen, *pdwParmLen)) > MEM_TILED_CEILING))
3041 {
3042 rc = DosAllocMem(&pTiledParm, dwParmMaxLen, PAG_READ | PAG_WRITE);
3043 if (rc)
3044 goto _exit_ioctl;
3045
3046 flagTiledParm = TRUE;
3047 }
3048
3049 if (pTiledData && (((DWORD)pTiledData + max(dwDataMaxLen, *pdwDataLen)) > MEM_TILED_CEILING))
3050 {
3051 rc = DosAllocMem(&pTiledData, dwDataMaxLen, PAG_READ | PAG_WRITE);
3052 if (rc)
3053 goto _exit_ioctl;
3054
3055 flagTiledData = TRUE;
3056 }
3057
3058 // copy data from real buffers to
3059 // bounce buffers if necessary
3060 if (pTiledParm != pParm)
3061 memcpy(pTiledParm, pParm, *pdwParmLen);
3062
3063 if (pTiledData != pData)
3064 memcpy(pTiledData, pData, *pdwDataLen);
3065
3066
3067 rc = DosDevIOCtl( (HFILE)hFile, dwCat, dwFunc,
3068 pParm, dwParmMaxLen, pdwParmLen,
3069 pData, dwDataMaxLen, pdwDataLen);
3070
3071 // copy data from bounce buffers to real
3072 // target buffers if necessary
3073 if (pTiledParm != pParm)
3074 memcpy(pParm, pTiledParm, *pdwParmLen);
3075
3076 if (pTiledData != pData)
3077 memcpy(pData, pTiledData, *pdwDataLen);
3078
3079
3080 _exit_ioctl:
3081
3082 // deallocate bounce buffers
3083 if (flagTiledParm)
3084 DosFreeMem(pTiledParm);
3085
3086 if (flagTiledData)
3087 DosFreeMem(pTiledData);
3088
3089 rc = error2WinError(rc, ERROR_INVALID_HANDLE);
3090 SetLastError(rc);
3091 return (DWORD)rc;
3092}
3093
3094/**
3095 * Pure wrapper for DosQueryModulName which returns the OS/2 returncode.
3096 * @returns Returncode from DosQueryModuleName.
3097 * @param hModule Handle of the module which name we query.
3098 * @param cchName Length of the output name buffer.
3099 * @param pszname Pointer to the output name buffer.
3100 * @status Completely implemented.
3101 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
3102 */
3103ULONG OSLibDosQueryModuleName(ULONG hModule, int cchName, char *pszName)
3104{
3105 return DosQueryModuleName(hModule, cchName, pszName);
3106}
3107
3108
3109HINSTANCE OSLibDosLoadModule(LPSTR szModName)
3110{
3111 APIRET rc;
3112 HMODULE hModule = NULLHANDLE;
3113 char name[ CCHMAXPATH ];
3114
3115 rc = DosLoadModule(name, CCHMAXPATH, szModName, &hModule);
3116 if(rc) {
3117 SetLastError(error2WinError(rc,ERROR_FILE_NOT_FOUND));
3118 return 0;
3119 }
3120 SetLastError(ERROR_SUCCESS_W);
3121 return hModule;
3122}
3123//******************************************************************************
3124//******************************************************************************
3125void OSLibDosFreeModule(HINSTANCE hinst)
3126{
3127 DosFreeModule(hinst);
3128}
3129//******************************************************************************
3130//******************************************************************************
3131ULONG OSLibDosQuerySysInfo(ULONG iStart, ULONG iLast, PVOID pBuf, ULONG cbBuf)
3132{
3133 APIRET rc;
3134
3135 rc = DosQuerySysInfo(iStart, iLast, pBuf, cbBuf);
3136 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
3137 return rc;
3138}
3139//******************************************************************************
3140//returned length is number of characters required or used for current dir
3141//*excluding* terminator
3142//******************************************************************************
3143ULONG OSLibDosQueryDir(DWORD length, LPSTR lpszCurDir)
3144{
3145 ULONG drivemap, currentdisk, len;
3146 char *lpszCurDriveAndDir = lpszCurDir +3;
3147 APIRET rc;
3148
3149 len = (length > 3) ? length - 3 : 0;
3150
3151 rc = DosQueryCurrentDir(0, lpszCurDriveAndDir, &len);
3152 if(rc != ERROR_BUFFER_OVERFLOW)
3153 {
3154 if(rc)
3155 {
3156 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER));
3157 return 0;
3158 }
3159 len = strlen(lpszCurDriveAndDir) + 3;
3160
3161 // Dir returned by DosQueryCurDir doesn't include drive, so add it
3162 DosQueryCurrentDisk(&currentdisk, &drivemap);
3163
3164 if(isupper(lpszCurDir[3])) {
3165 lpszCurDir[0] = (char)('A' - 1 + currentdisk);
3166 }
3167 else lpszCurDir[0] = (char)('a' - 1 + currentdisk);
3168
3169 lpszCurDir[1] = ':';
3170 lpszCurDir[2] = '\\';
3171 }
3172 else len += 3; // + 3 since DosQueryCurDir doesn't include drive
3173
3174 SetLastError(ERROR_SUCCESS_W);
3175 return len;
3176}
3177//******************************************************************************
3178//******************************************************************************
3179BOOL OSLibDosBeep(DWORD ulFreq, DWORD ulDuration)
3180{
3181 APIRET rc;
3182
3183 if (ulDuration == -1)
3184 {
3185 SetLastError(ERROR_NOT_SUPPORTED_W);
3186 return FALSE;
3187 }
3188 rc = DosBeep(ulFreq, ulDuration);
3189 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
3190
3191 return (rc == 0);
3192}
3193//******************************************************************************
3194//******************************************************************************
3195ULONG OSLibDosGetModuleFileName(HMODULE hModule, LPTSTR lpszPath, DWORD cchPath)
3196{
3197 PTIB pTIB;
3198 PPIB pPIB;
3199 APIRET rc;
3200
3201 if(hModule == -1 || hModule == 0)
3202 {
3203 DosGetInfoBlocks(&pTIB, &pPIB);
3204 hModule = pPIB->pib_hmte;
3205 }
3206 *lpszPath = 0;
3207 rc = DosQueryModuleName(hModule, cchPath, lpszPath);
3208
3209 DWORD len = strlen(lpszPath);
3210 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
3211 return len;
3212}
3213//******************************************************************************
3214//******************************************************************************
3215ULONG OSLibDosGetProcAddress(HMODULE hModule, LPCSTR lpszProc)
3216{
3217 APIRET rc;
3218 PFN pfn = NULL;
3219 ULONG ordinal = (((ULONG)lpszProc) <= 0xFFFF) ? (ULONG)lpszProc : 0;
3220 HMODULE hmod = (HMODULE)hModule;
3221
3222 rc = DosQueryProcAddr( hmod, ordinal, (PSZ)lpszProc, &pfn );
3223 if(rc == ERROR_INVALID_HANDLE && pfn == NULL) {
3224 CHAR pszError[32], pszModule[CCHMAXPATH];
3225
3226 if(DosQueryModuleName( hmod, CCHMAXPATH, pszModule ) == 0 &&
3227 DosLoadModule( pszError, 32, pszModule, &hmod ) == 0)
3228 {
3229 rc = DosQueryProcAddr(hmod, ordinal, (PSZ)lpszProc, &pfn);
3230 }
3231 }
3232 SetLastError(error2WinError(rc,ERROR_INVALID_HANDLE));
3233
3234 return (ULONG)pfn;
3235}
3236//******************************************************************************
3237//******************************************************************************
3238BOOL OSLibDosSetThreadAffinity(DWORD dwThreadAffinityMask)
3239{
3240 static PROC_DosSetThreadAffinity pfnDosSetThreadAffinity = NULL;
3241 static BOOL fInit = FALSE;
3242 MPAFFINITY mask;
3243 APIRET rc;
3244
3245 if(fInit == FALSE && pfnDosSetThreadAffinity == NULL)
3246 {
3247 ULONG nrCPUs;
3248
3249 rc = DosQuerySysInfo(QSV_NUMPROCESSORS, QSV_NUMPROCESSORS, &nrCPUs, sizeof(nrCPUs));
3250 if (rc != 0 || nrCPUs == 1)
3251 {//not supported
3252 fInit = TRUE;
3253 SetLastError(ERROR_SUCCESS_W);
3254 return TRUE;
3255 }
3256
3257 HMODULE hDoscalls;
3258 if(DosQueryModuleHandle("DOSCALLS", &hDoscalls) == NO_ERROR) {
3259 DosQueryProcAddr(hDoscalls, 564, NULL, (PFN *)&pfnDosSetThreadAffinity);
3260 }
3261 fInit = TRUE;
3262 }
3263 if(fInit && pfnDosSetThreadAffinity == NULL) {
3264 SetLastError(ERROR_SUCCESS_W);
3265 return TRUE;
3266 }
3267 USHORT sel = RestoreOS2FS();
3268
3269 mask.mask[0] = dwThreadAffinityMask;
3270 mask.mask[1] = 0; //TODO: this might not be a good idea, but then again, not many people have > 32 cpus
3271
3272 rc = pfnDosSetThreadAffinity(&mask);
3273 SetFS(sel);
3274
3275 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER));
3276 return (rc == NO_ERROR);
3277}
3278//******************************************************************************
3279//******************************************************************************
3280BOOL OSLibDosQueryAffinity(DWORD fMaskType, DWORD *pdwThreadAffinityMask)
3281{
3282 static PROC_DosQueryThreadAffinity pfnDosQueryThreadAffinity = NULL;
3283 static BOOL fInit = FALSE;
3284 MPAFFINITY mask;
3285 APIRET rc;
3286
3287 if(fInit == FALSE && pfnDosQueryThreadAffinity == NULL)
3288 {
3289 ULONG nrCPUs;
3290
3291 rc = DosQuerySysInfo(QSV_NUMPROCESSORS, QSV_NUMPROCESSORS, &nrCPUs, sizeof(nrCPUs));
3292 if (rc != 0 || nrCPUs == 1)
3293 {//not supported
3294 fInit = TRUE;
3295 *pdwThreadAffinityMask = 1;
3296 SetLastError(ERROR_SUCCESS_W);
3297 return TRUE;
3298 }
3299
3300 HMODULE hDoscalls;
3301 if(DosQueryModuleHandle("DOSCALLS", &hDoscalls) == NO_ERROR) {
3302 DosQueryProcAddr(hDoscalls, 563, NULL, (PFN *)&pfnDosQueryThreadAffinity);
3303 }
3304 fInit = TRUE;
3305 }
3306 if(fInit && pfnDosQueryThreadAffinity == NULL) {
3307 *pdwThreadAffinityMask = 1;
3308 SetLastError(ERROR_SUCCESS_W);
3309 return TRUE;
3310 }
3311
3312 ULONG scope = (fMaskType == MASK_SYSTEM) ? AFNTY_SYSTEM : AFNTY_THREAD;
3313
3314 USHORT sel = RestoreOS2FS();
3315
3316 rc = pfnDosQueryThreadAffinity(scope, &mask);
3317 SetFS(sel);
3318
3319 if(rc == NO_ERROR) {
3320 *pdwThreadAffinityMask = mask.mask[0];
3321 }
3322
3323 SetLastError(error2WinError(rc,ERROR_INVALID_PARAMETER));
3324 return (rc == NO_ERROR);
3325}
3326//******************************************************************************
3327//******************************************************************************
3328void OSLibDosSleep(ULONG msecs)
3329{
3330 DosSleep(msecs);
3331}
3332//******************************************************************************
3333//******************************************************************************
3334DWORD OSLibDosDevConfig(PVOID pdevinfo,
3335 ULONG item)
3336{
3337 return (DWORD)DosDevConfig(pdevinfo, item);
3338}
3339//******************************************************************************
3340//******************************************************************************
3341DWORD OSLibDosGetNumPhysDrives()
3342{
3343 USHORT usNumDrives = 0; /* Data return buffer */
3344 ULONG ulDataLen = sizeof(USHORT); /* Data return buffer length */
3345 APIRET rc = NO_ERROR; /* Return code */
3346
3347 /* Request a count of the number of partitionable disks in the system */
3348
3349 rc = DosPhysicalDisk(INFO_COUNT_PARTITIONABLE_DISKS,
3350 &usNumDrives,
3351 ulDataLen,
3352 NULL, /* No parameter for this function */
3353 0L);
3354
3355 if (rc != NO_ERROR) {
3356 dprintf(("DosPhysicalDisk error: return code = %u\n", rc));
3357 return 0;
3358 }
3359 else {
3360 dprintf(("DosPhysicalDisk: %u partitionable disk(s)\n",usNumDrives));
3361 }
3362 return usNumDrives;
3363}
3364//******************************************************************************
3365//******************************************************************************
3366
Note: See TracBrowser for help on using the repository browser.