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

Last change on this file since 21638 was 21638, checked in by dmik, 14 years ago

kernel32: GetFileAttributesEx(): Interpret paths like 'X:' as 'X:\' instead of reporting an error, for compatibility with Win32.

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