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

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

kernel32: Fixed: GetFileInformation() would fail with ERROR_ACCESS_DEINIED on a file opened in write-only mode if it is located on an HPFS386 volume (HPFS386 treats EAs as part of file data, not part of file attributes).

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