source: trunk/src/kernel32/oslibdos.cpp

Last change on this file was 22055, checked in by dmik, 13 years ago

kernel32: Use console input/output mode only if handle is attached to a real console.

Previously it would use this mode (which reads/writes directly to the attached VIO window)
for all character devices (e.g. NUL) which was clearly wrong.

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