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

Last change on this file since 22032 was 22025, checked in by dmik, 13 years ago

kernel32: Implement GetFileInformationByHandle for directories.

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