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

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

Fixed a regression in r21674.

This broke the Select Directory dialog in SmartSVN/SmartGit
since GetFileAttributesEx(x:\) would returne a failure again.

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