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

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

kernel32: Implemented generating the high/low index values (using a CRC32 and a hash function on the fuill file name) and filling up the volume serial number in the BY_HANDLE_FILE_INFORMATION structure returned by GetFileInformationByHandle().

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