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

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

GetFileAttributesEx: Accept paths with trailing slashes.

The Win32 version of GetFileAttributesEx() treats paths like
'some\path\' as if they were 'some\path' -- hence Odin should
behave the same instead of always returning a failure on such
paths (PATH_NOT_FOUND) as DosQueryPathInfo does on OS/2.

This in particular fixes the Log command on repository roots
in SmartGit (OpenJDK).

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