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

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

kernel32: Report ERROR_MOD_NOT_FOUND from LoadLibrary() when it fails to load a DLL due to missing import modules, to mimic Win32 behavior.

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