Win32OperatingSystem.st
changeset 6293 e73c204b9f1e
parent 6288 dad5c4e592e0
child 6297 7d0a04fb50be
--- a/Win32OperatingSystem.st	Tue Dec 11 18:10:28 2001 +0100
+++ b/Win32OperatingSystem.st	Tue Dec 11 18:43:56 2001 +0100
@@ -44,6 +44,20 @@
 	privateIn:Win32OperatingSystem
 !
 
+OSFileHandle subclass:#Win32FILEHandle
+	instanceVariableNames:''
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:Win32OperatingSystem
+!
+
+OSFileHandle subclass:#Win32Handle
+	instanceVariableNames:''
+	classVariableNames:''
+	poolDictionaries:''
+	privateIn:Win32OperatingSystem
+!
+
 !Win32OperatingSystem primitiveDefinitions!
 %{
 
@@ -1173,7 +1187,7 @@
 
             case ERROR_INVALID_HANDLE:
                 sym = @symbol(ERROR_INVALID_HANDLE);
-                typ = @symbol(invalidArgumentSignal);
+                typ = @symbol(invalidArgumentsSignal);
                 break;
 
             case ERROR_NOT_ENOUGH_MEMORY:
@@ -1188,12 +1202,12 @@
 
             case ERROR_INVALID_DATA:
                 sym = @symbol(ERROR_INVALID_DATA);
-                typ = @symbol(invalidArgumentSignal);
+                typ = @symbol(invalidArgumentsSignal);
                 break;
 
             case ERROR_INVALID_NAME:
                 sym = @symbol(ERROR_INVALID_NAME);
-                typ = @symbol(invalidArgumentSignal);
+                typ = @symbol(invalidArgumentsSignal);
                 break;
 
             case ERROR_ARENA_TRASHED:
@@ -1252,7 +1266,7 @@
 
             case ERROR_INVALID_PARAMETER:
                 sym = @symbol(ERROR_INVALID_PARAMETER);
-                typ = @symbol(invalidArgumentSignal);
+                typ = @symbol(invalidArgumentsSignal);
                 break;
 
             case ERROR_NET_WRITE_FAULT:
@@ -1297,7 +1311,7 @@
 
             case ERROR_INVALID_DRIVE:
                 sym = @symbol(ERROR_INVALID_DRIVE);
-                typ = @symbol(invalidArgumentSignal);
+                typ = @symbol(invalidArgumentsSignal);
                 break;
 
             case ERROR_WRONG_DISK:
@@ -1307,7 +1321,7 @@
 
             case ERROR_CURRENT_DIRECTORY:
                 sym = @symbol(ERROR_CURRENT_DIRECTORY);
-                typ = @symbol(invalidArgumentSignal);
+                typ = @symbol(invalidArgumentsSignal);
                 break;
 
             /*
@@ -1331,7 +1345,7 @@
 
             case ERROR_NOT_DOS_DISK:
                 sym = @symbol(ERROR_NOT_DOS_DISK);
-                typ = @symbol(invalidArgumentSignal);
+                typ = @symbol(invalidArgumentsSignal);
                 break;
 
             case ERROR_OUT_OF_PAPER:
@@ -3111,6 +3125,14 @@
     "Modified: 29.6.1996 / 14:06:54 / cg"
 !
 
+createFileForReadAppend:pathName
+     ^ self openFile:pathName attributes:#(#'GENERIC_READ' #'GENERIC_WRITE')
+!
+
+createFileForReadWrite:pathName
+     ^ self openFile:pathName attributes:#(#'GENERIC_READ' #'GENERIC_WRITE')
+!
+
 linkFile:oldPath to:newPath
     "link the file 'oldPath' to 'newPath'. The link will be a hard link.
      Return true if successful, false if not."
@@ -3132,6 +3154,125 @@
     "
 !
 
+openFile:pathName attributes:attributeSpec
+    "non public internal helper.
+     open a file, return an os specific fileHandle. 
+     attributes is a collection of symbols specifying how the file is
+     to be opened."
+
+    |fileHandle errorNumber|
+
+    fileHandle := Win32Handle new.
+
+%{
+    HANDLE h;
+    char *name;
+    OBJ *ap = __ArrayInstPtr(attributeSpec)->a_element;
+    int numAttrib = __arraySize(attributeSpec);
+    int i;
+    DWORD access, share, create, attr;
+
+    if (! __isString(pathName)) {
+        fileHandle = nil;
+        goto badArgument;
+    }
+    if (! __isArray(attributeSpec)) {
+        fileHandle = nil;
+        goto badArgument;
+    }
+
+    name = __stringVal(pathName);    
+
+    share = 0;
+    access = 0;
+    create = 0;
+    attr = 0;
+
+    for (i=0; i<numAttrib;i++) {
+        OBJ attrSym = ap[i];
+
+        if (attrSym == @symbol(FILE_SHARE_READ)) {
+            share |= FILE_SHARE_READ;
+        } else if (attrSym == @symbol(FILE_SHARE_WRITE)) {
+            share |= FILE_SHARE_WRITE;
+
+        } else if (attrSym == @symbol(GENERIC_READ)) {
+            access |= GENERIC_READ;
+        } else if (attrSym == @symbol(GENERIC_WRITE)) {
+            access |= GENERIC_WRITE;
+
+        } else if (attrSym == @symbol(CREATE_NEW)) {
+            create |= CREATE_NEW;
+        } else if (attrSym == @symbol(CREATE_ALWAYS)) {
+            create |= CREATE_ALWAYS;
+        } else if (attrSym == @symbol(OPEN_EXISTING)) {
+            create |= OPEN_EXISTING;
+        } else if (attrSym == @symbol(OPEN_ALWAYS)) {
+            create |= OPEN_ALWAYS;
+        } else if (attrSym == @symbol(TRUNCATE_EXISTING)) {
+            create |= TRUNCATE_EXISTING;
+
+        } else if (attrSym == @symbol(FILE_ATTRIBUTE_HIDDEN)) {
+            attr |= FILE_ATTRIBUTE_HIDDEN;
+        } else if (attrSym == @symbol(FILE_ATTRIBUTE_READONLY)) {
+            attr |= FILE_ATTRIBUTE_READONLY;
+        } else if (attrSym == @symbol(FILE_ATTRIBUTE_READONLY)) {
+            attr |= FILE_ATTRIBUTE_READONLY;
+        } else if (attrSym == @symbol(FILE_FLAG_WRITE_THROUGH)) {
+            attr |= FILE_FLAG_WRITE_THROUGH;
+        } else if (attrSym == @symbol(FILE_FLAG_SEQUENTIAL_SCAN)) {
+            attr |= FILE_FLAG_SEQUENTIAL_SCAN;
+        } else if (attrSym == @symbol(FILE_FLAG_DELETE_ON_CLOSE)) {
+            attr |= FILE_FLAG_DELETE_ON_CLOSE;
+        } else {
+            fprintf(stderr, "Win32OS [warning]: unsupported open mode\n");
+        }
+    }
+fprintf(stderr, "name:<%s> access:%x share:%x create:%x attr:%x\n",
+                name, access, share, create, attr);
+
+    h = CreateFile(name, access, share, 0 /* sa */, create, attr, 0 /* hTempl */);
+    if (h != INVALID_HANDLE_VALUE) {
+        __externalAddressVal(fileHandle) = (void *)h;  
+    } else {
+        fileHandle = nil;
+        errorNumber = __MKSMALLINT( __WIN32_ERR(GetLastError()) );
+    }
+
+badArgument: ;
+%}.
+    fileHandle notNil ifTrue:[
+        fileHandle registerForFinalization.
+        ^ fileHandle.
+    ].
+    errorNumber isNil ifTrue:[
+        self error:'invalid argument(s)'.
+    ] ifFalse:[
+        (self errorHolderForNumber:errorNumber) reportError
+    ].
+    self halt.
+!
+
+openFileForAppend:pathName
+     ^ self halt
+!
+
+openFileForRead:pathName
+     ^ self openFile:pathName attributes:#(#'GENERIC_READ')
+!
+
+openFileForReadAppend:pathName
+     ^ self halt
+!
+
+openFileForReadWrite:pathName
+     ^ self openFile:pathName attributes:#(#'GENERIC_READ' #'GENERIC_WRITE')
+!
+
+openFileForWrite:pathName
+     ^ self openFile:pathName attributes:#(#'GENERIC_WRITE')
+!
+
 recursiveCopyDirectory:sourcePathName to:destination
     "copy the directory named 'sourcePathName' and all contained files/directories to 'destination'.
      Return true if successful."
@@ -8370,9 +8511,283 @@
     "Created: / 19.5.1999 / 21:45:05 / cg"
 ! !
 
+!Win32OperatingSystem::Win32FILEHandle class methodsFor:'documentation'!
+
+documentation
+"
+    I represent a FILE*, as used in the stdio library.
+    Since most stdio libs are inherently buggy, thread-unsave
+    and hard to use in a multithreading environment,
+    these will no longer be used in future ST/X versions.
+    However, they may be useful when interfacing to external
+    libraries...
+"
+!
+
+version
+    ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.102 2001-12-11 17:43:56 cg Exp $'
+! !
+
+!Win32OperatingSystem::Win32FILEHandle methodsFor:'release'!
+
+closeFile
+    "close the file"
+
+%{
+    FILE *f = (FILE *)(__externalAddressVal(self));
+
+    if (f) {
+        __externalAddressVal(self) = NULL;
+        fclose(f);
+    }
+%}.
+! !
+
+!Win32OperatingSystem::Win32Handle class methodsFor:'documentation'!
+
+documentation
+"
+    I represent a generic HANDLE, which can be closed via CloseHandle.
+"
+!
+
+version
+    ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.102 2001-12-11 17:43:56 cg Exp $'
+! !
+
+!Win32OperatingSystem::Win32Handle methodsFor:'io'!
+
+readBytes:count into:aByteBuffer startingAt:firstIndex
+    "read count bytes into a byte-buffer;
+     Return the number of bytes read (negative on error)"
+
+%{
+#if 0
+    unsigned char *extPtr;
+    int nRead = -1;
+    INT fd = (INT)(__externalAddressVal(self));
+    INT cnt, offs;
+    int nInstBytes, objSize;
+
+    if (! __bothSmallInteger(count, firstIndex)) {
+        goto bad;
+    }
+    cnt = __smallIntegerVal(count);
+    offs = __smallIntegerVal(firstIndex) - 1;
+
+    if (fd < 0) {
+        goto bad;
+    }
+    if (__isExternalBytes(aByteBuffer)) {
+        OBJ sz;
+
+        nInstBytes = 0;
+        extPtr = (char *)(__externalBytesAddress(aByteBuffer));
+        sz = __externalBytesSize(aByteBuffer);
+        if (__isSmallInteger(sz)) {
+            objSize = __smallIntegerVal(sz);
+        } else {
+            objSize = -1; /* unknown */
+        }
+    } else {
+        OBJ oClass;
+        int nInstVars;
+
+        oClass = __Class(aByteBuffer);
+        switch (__smallIntegerVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
+            case BYTEARRAY:
+            case WORDARRAY:
+            case LONGARRAY:
+            case SWORDARRAY:
+            case SLONGARRAY:
+            case FLOATARRAY:
+            case DOUBLEARRAY:
+                break;
+            default:
+                goto bad;
+        }
+        extPtr = (char *)0;
+        nInstVars = __smallIntegerVal(__ClassInstPtr(oClass)->c_ninstvars);
+        nInstBytes = __OBJS2BYTES__(nInstVars);
+        objSize = __Size(aByteBuffer) - OHDR_SIZE - nInstBytes;
+    }
+    if ((offs >= 0)
+     && (cnt >= 0)
+     && ((objSize == -1) || (objSize >= (cnt + offs)))) {
+        nRead = 0;
+
+        do {
+            int n;
+
+            if (extPtr) {
+                n = read(fd, extPtr+offs, cnt);
+            } else {
+                char *bp;
+
+                /*
+                 * on interrupt, anObject may be moved to another location.
+                 * So we recompute the byte-address here.
+                 */
+                bp = __ByteArrayInstPtr(aByteBuffer)->ba_element + nInstBytes;
+
+                n = read(fd, bp + offs, cnt);
+            }
+            if (n > 0) {
+                cnt -= n;
+                offs += n;
+                nRead += n;
+            } else {
+                if (n < 0) {
+                    if (errno == EINTR) {
+                        continue;
+                    }
+                    break;
+                }
+            }
+        } while (cnt > 0);
+
+        RETURN (__mkSmallInteger(nRead));
+    }
+bad: ;   
+#endif
+%}.
+    ^ self primitiveFailed
+
+    "
+     |h buff n|
+
+     h := self basicNew.
+     h setFileDescriptor:0.
+     buff := ByteArray new:10. buff inspect.
+     n := h readBytes:10 into:buff startingAt:1.
+     Transcript show:n; space; showCR:buff.
+    "
+!
+
+writeBytes:count from:aByteBuffer startingAt:firstIndex
+    "write count bytes from a byte-buffer;
+     Return the number of bytes written (negative on error)"
+
+%{
+#if 0
+    unsigned char *extPtr;
+    int nWritten = -1;
+    INT fd = (INT)(__externalAddressVal(self));
+    INT cnt, offs;
+    int nInstBytes, objSize;
+
+    if (! __bothSmallInteger(count, firstIndex)) {
+        goto bad;
+    }
+    cnt = __smallIntegerVal(count);
+    offs = __smallIntegerVal(firstIndex) - 1;
+
+    if (fd < 0) {
+        goto bad;
+    }
+    if (__isExternalBytes(aByteBuffer)) {
+        OBJ sz;
+
+        nInstBytes = 0;
+        extPtr = (char *)(__externalBytesAddress(aByteBuffer));
+        sz = __externalBytesSize(aByteBuffer);
+        if (__isSmallInteger(sz)) {
+            objSize = __smallIntegerVal(sz);
+        } else {
+            objSize = -1; /* unknown */
+        }
+    } else {
+        OBJ oClass;
+        int nInstVars;
+
+        oClass = __Class(aByteBuffer);
+        switch (__smallIntegerVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
+            case BYTEARRAY:
+            case WORDARRAY:
+            case LONGARRAY:
+            case SWORDARRAY:
+            case SLONGARRAY:
+            case FLOATARRAY:
+            case DOUBLEARRAY:
+                break;
+            default:
+                goto bad;
+        }
+        extPtr = (char *)0;
+        nInstVars = __smallIntegerVal(__ClassInstPtr(oClass)->c_ninstvars);
+        nInstBytes = __OBJS2BYTES__(nInstVars);
+        objSize = __Size(aByteBuffer) - OHDR_SIZE - nInstBytes;
+    }
+    if ((offs >= 0)
+     && (cnt >= 0)
+     && ((objSize == -1) || (objSize >= (cnt + offs)))) {
+        nWritten = 0;
+
+        do {
+            int n;
+
+            if (extPtr) {
+                n = write(fd, extPtr+offs, cnt);
+            } else {
+                char *bp;
+
+                /*
+                 * on interrupt, anObject may be moved to another location.
+                 * So we recompute the byte-address here.
+                 */
+                bp = __ByteArrayInstPtr(aByteBuffer)->ba_element + nInstBytes;
+
+                n = write(fd, bp + offs, cnt);
+            }
+            if (n > 0) {
+                cnt -= n;
+                offs += n;
+                nWritten += n;
+            } else {
+                if (n < 0) {
+                    if (errno == EINTR) {
+                        continue;
+                    }
+                    break;
+                }
+            }
+        } while (cnt > 0);
+
+        RETURN (__mkSmallInteger(nWritten));
+    }
+bad: ;   
+#endif
+%}.
+    ^ self primitiveFailed
+
+    "
+     |h buff n|
+
+     h := self basicNew.
+     h setFileDescriptor:1.
+     buff := '12345678901234567890'.
+     n := h writeBytes:10 from:buff startingAt:1.
+    "
+! !
+
+!Win32OperatingSystem::Win32Handle methodsFor:'release'!
+
+closeFile
+    "close the handle"
+
+%{
+    HANDLE h = (HANDLE)(__externalAddressVal(self));
+
+    if (h) {
+        __externalAddressVal(self) = (HANDLE)0;
+        CloseHandle(h);
+    }
+%}.
+! !
+
 !Win32OperatingSystem class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.101 2001-12-11 16:04:05 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.102 2001-12-11 17:43:56 cg Exp $'
 ! !
 Win32OperatingSystem initialize!