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

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

Fix for Flash10 video. Flash10 provides OffsetHigh, but it have no sence

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