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

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

Merge branch gcc-kmk to trunk.

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