# HG changeset patch # User Claus Gittinger # Date 1170841822 -3600 # Node ID 92efacf8b050ed7628a80c2e42c63cea6f7880ea # Parent 44ba935b47bac78b3c9ca54d41566ac5a724a1fa getLinkTarget is now done lazyly. diff -r 44ba935b47ba -r 92efacf8b050 Win32OperatingSystem.st --- a/Win32OperatingSystem.st Mon Feb 05 16:40:19 2007 +0100 +++ b/Win32OperatingSystem.st Wed Feb 07 10:50:22 2007 +0100 @@ -3622,71 +3622,72 @@ IPersistFile *ppf; if (! __isString(aPathName)) { - console_fprintf(stderr, "invalid argument\n"); - goto error; + console_fprintf(stderr, "invalid argument\n"); + goto error; } hres = CoInitialize(NULL); if (! SUCCEEDED(hres)) { - console_fprintf(stderr, "Could not open the COM library\n"); - goto error; + console_fprintf(stderr, "Could not open the COM library\n"); + goto error; } hres = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, - &IID_IShellLink, (LPVOID *)&psl); + &IID_IShellLink, (LPVOID *)&psl); if (SUCCEEDED(hres)) { - hres = psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile, &ppf); - - if (SUCCEEDED(hres)) { - WORD wsz[MAX_PATH]; - - MultiByteToWideChar(CP_ACP, 0, __stringVal(aPathName), -1, wsz, MAX_PATH); - - hres = ppf->lpVtbl->Load(ppf, wsz, STGM_READ); - if (SUCCEEDED(hres)) { + hres = psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile, &ppf); + + if (SUCCEEDED(hres)) { + WORD wsz[MAX_PATH]; + + MultiByteToWideChar(CP_ACP, 0, __stringVal(aPathName), -1, wsz, MAX_PATH); + + hres = ppf->lpVtbl->Load(ppf, wsz, STGM_READ); + if (SUCCEEDED(hres)) { #if 0 - hres = psl->lpVtbl->Resolve(psl, 0, SLR_ANY_MATCH|SLR_NO_UI); -#endif - if (SUCCEEDED(hres)) { - hres = psl->lpVtbl->GetPath(psl, szGotPath, MAX_PATH, - (WIN32_FIND_DATA *)&wfd, 0 /* SLGP_SHORTPATH */ ); - if (!SUCCEEDED(hres)) { - console_fprintf(stderr, "GetPath failed!\n"); - } else { + hres = psl->lpVtbl->Resolve(psl, 0, SLR_ANY_MATCH|SLR_NO_UI); +#endif + if (SUCCEEDED(hres)) { + hres = psl->lpVtbl->GetPath(psl, szGotPath, MAX_PATH, + (WIN32_FIND_DATA *)&wfd, 0 /* SLGP_SHORTPATH */ ); + if (!SUCCEEDED(hres)) { + console_fprintf(stderr, "GetPath failed!\n"); + } else { #if 0 - console_printf("This points to %s\n", wfd.cFileName); console_fflush(stdout); - console_printf("Path is %s\n", szGotPath); console_fflush(stdout); - if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - console_printf("This is a directory\n"); console_fflush(stdout); - } -#endif - resolvedPath = __MKSTRING(szGotPath); + console_printf("This points to %s\n", wfd.cFileName); console_fflush(stdout); + console_printf("Path is %s\n", szGotPath); console_fflush(stdout); + if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + console_printf("This is a directory\n"); console_fflush(stdout); + } +#endif + resolvedPath = __MKSTRING(szGotPath); #if 0 - hres = psl->lpVtbl->GetWorkingDirectory(psl, szGotPath, MAX_PATH); - if (!SUCCEEDED(hres)) { - console_fprintf(stderr, "GetWorkingDirectory failed!\n"); - } else { - console_printf("In Directory %s\n", szGotPath); - } -#endif - } - } - } else { - console_fprintf(stderr, "IPersistFile Load Error\n"); - } - ppf->lpVtbl->Release(ppf); - } else { - console_fprintf(stderr, "QueryInterface Error\n"); - } - psl->lpVtbl->Release(psl); + hres = psl->lpVtbl->GetWorkingDirectory(psl, szGotPath, MAX_PATH); + if (!SUCCEEDED(hres)) { + console_fprintf(stderr, "GetWorkingDirectory failed!\n"); + } else { + console_printf("In Directory %s\n", szGotPath); + } +#endif + } + } + } else { + console_fprintf(stderr, "IPersistFile Load Error\n"); + } + ppf->lpVtbl->Release(ppf); + } else { + console_fprintf(stderr, "QueryInterface Error\n"); + } + psl->lpVtbl->Release(psl); } else { - console_fprintf(stderr, "CoCreateInstance Error - hres = %08x\n", hres); + console_fprintf(stderr, "CoCreateInstance Error - hres = %08x\n", hres); } error: ; %}. resolvedPath notNil ifTrue:[^ resolvedPath ]. - self primitiveFailed. + "/ self primitiveFailed. + ^ nil. " OperatingSystem getLinkTarget:'C:\Dokumente und Einstellungen\cg\Favoriten\Incoming.lnk' @@ -3694,7 +3695,7 @@ " "Created: / 07-11-2006 / 10:52:44 / cg" - "Modified: / 08-11-2006 / 12:20:33 / cg" + "Modified: / 07-02-2007 / 10:37:48 / cg" ! linkFile:oldPath to:newPath @@ -4416,16 +4417,16 @@ "return some object filled with info for the file 'aPathName'; the info (for which corresponding access methods are understood by the returned object) is: - type - a symbol giving the files type - mode - numeric access mode - uid - owners user id - gid - owners group id - size - files size - id - files number (i.e. inode number) - accessed - last access time (as Timestamp) - modified - last modification time (as Timestamp) - statusChanged - last status change time (as Timestamp) - alternativeName - (windows only:) the MSDOS name of the file + type - a symbol giving the files type + mode - numeric access mode + uid - owners user id + gid - owners group id + size - files size + id - files number (i.e. inode number) + accessed - last access time (as Timestamp) + modified - last modification time (as Timestamp) + statusChanged - last status change time (as Timestamp) + alternativeName - (windows only:) the MSDOS name of the file Some of the fields may be returned as nil on systems which do not provide all of the information. @@ -4439,8 +4440,10 @@ info := self linkInfoOf:aPathName. (info notNil and:[info isSymbolicLink]) ifTrue:[ - target := info path. - ^ self linkInfoOf:target. + target := info path. + target notNil ifTrue:[ + ^ self linkInfoOf:target. + ] ]. ^ info @@ -4451,7 +4454,7 @@ (OperatingSystem infoOf:'/') accessed " - "Modified: / 07-11-2006 / 16:27:02 / cg" + "Modified: / 07-02-2007 / 10:37:14 / cg" ! isDirectory:aPathName @@ -4719,16 +4722,16 @@ "return some object filled with info for the file 'aPathName'; the info (for which corresponding access methods are understood by the returned object) is: - type - a symbol giving the files type - mode - numeric access mode - uid - owners user id - gid - owners group id - size - files size - id - files number (i.e. inode number) - accessed - last access time (as Timestamp) - modified - last modification time (as Timestamp) - statusChanged - last status change time (as Timestamp) - alternativeName - (windows only:) the MSDOS name of the file + type - a symbol giving the files type + mode - numeric access mode + uid - owners user id + gid - owners group id + size - files size + id - files number (i.e. inode number) + accessed - last access time (as Timestamp) + modified - last modification time (as Timestamp) + statusChanged - last status change time (as Timestamp) + alternativeName - (windows only:) the MSDOS name of the file Some of the fields may be returned as nil on systems which do not provide all of the information. @@ -4754,145 +4757,147 @@ unsigned INT ino; if (__isString(aPathName)) { - HANDLE hFile; - FILETIME tempFileTime; - SYSTEMTIME creationTime; - SYSTEMTIME accessTime; - SYSTEMTIME modificationTime; - int modeBits = 0; - WIN32_FIND_DATA findStruct; + HANDLE hFile; + FILETIME tempFileTime; + SYSTEMTIME creationTime; + SYSTEMTIME accessTime; + SYSTEMTIME modificationTime; + int modeBits = 0; + WIN32_FIND_DATA findStruct; #ifdef DO_WRAP_CALLS - { - char _aPathName[MAXPATHLEN]; - - strncpy(_aPathName, __stringVal(aPathName), MAXPATHLEN-1); _aPathName[MAXPATHLEN-1] = '\0'; - do { - __threadErrno = 0; - hFile = STX_API_CALL2( "FindFirstFile", FindFirstFile, _aPathName, &findStruct); - } while ((hFile < 0) && (__threadErrno == EINTR)); - } -#else - hFile = FindFirstFile(__stringVal(aPathName), &findStruct); - if (hFile < 0) { - __threadErrno = __WIN32_ERR(GetLastError()); - } -#endif - if (! hFile || (hFile == (HANDLE)(-1)) || (hFile == INVALID_HANDLE_VALUE)) { - @global(LastErrorNumber) = __mkSmallInteger(__threadErrno); - } else { - FindClose(hFile); - - id = __mkSmallInteger(0); /* could get it by opening ... */ - size = __MKLARGEINT64(1, findStruct.nFileSizeLow, findStruct.nFileSizeHigh); - - if (findStruct.cFileName[0] != '\0') { - bcopy(findStruct.cFileName, fileNameBuffer, MAX_PATH); - fileNameBuffer[MAX_PATH] = '\0'; - fileName = __MKSTRING(fileNameBuffer); /* FULL name */ - } - - if (findStruct.cAlternateFileName[0] != '\0') { - bcopy(findStruct.cAlternateFileName, alternativeFileNameBuffer, 14); - alternativeFileNameBuffer[14] = '\0'; - alternativeName = __MKSTRING(alternativeFileNameBuffer); /* DOS name */ - } - - /* - * simulate access bits - */ - if (findStruct.dwFileAttributes & FILE_ATTRIBUTE_READONLY) { - modeBits = 0444; - } else { - modeBits = 0666; - } - - if (findStruct.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - type = @symbol(directory); - modeBits |= 0111; /* executable */ - } else { - type = @symbol(regular); - } - - mode = __mkSmallInteger(modeBits); - - /* - * sigh - convert from stupid time to useful time - */ - FileTimeToLocalFileTime(&findStruct.ftCreationTime, &tempFileTime); - FileTimeToSystemTime(&tempFileTime, &creationTime); - FileTimeToLocalFileTime(&findStruct.ftLastAccessTime, &tempFileTime); - FileTimeToSystemTime(&tempFileTime, &accessTime); - FileTimeToLocalFileTime(&findStruct.ftLastWriteTime, &tempFileTime); - FileTimeToSystemTime(&tempFileTime, &modificationTime); - aYr = __mkSmallInteger(accessTime.wYear); - aMon = __mkSmallInteger(accessTime.wMonth); - aDay = __mkSmallInteger(accessTime.wDay); - aHr = __mkSmallInteger(accessTime.wHour); - aMin = __mkSmallInteger(accessTime.wMinute); - aSec = __mkSmallInteger(accessTime.wSecond); - aMS = __mkSmallInteger(accessTime.wMilliseconds); - - mYr = __mkSmallInteger(modificationTime.wYear); - mMon = __mkSmallInteger(modificationTime.wMonth); - mDay = __mkSmallInteger(modificationTime.wDay); - mHr = __mkSmallInteger(modificationTime.wHour); - mMin = __mkSmallInteger(modificationTime.wMinute); - mSec = __mkSmallInteger(modificationTime.wSecond); - mMS = __mkSmallInteger(modificationTime.wMilliseconds); - - cYr = __mkSmallInteger(creationTime.wYear); - cMon = __mkSmallInteger(creationTime.wMonth); - cDay = __mkSmallInteger(creationTime.wDay); - cHr = __mkSmallInteger(creationTime.wHour); - cMin = __mkSmallInteger(creationTime.wMinute); - cSec = __mkSmallInteger(creationTime.wSecond); - cMS = __mkSmallInteger(creationTime.wMilliseconds); - } + { + char _aPathName[MAXPATHLEN]; + + strncpy(_aPathName, __stringVal(aPathName), MAXPATHLEN-1); _aPathName[MAXPATHLEN-1] = '\0'; + do { + __threadErrno = 0; + hFile = STX_API_CALL2( "FindFirstFile", FindFirstFile, _aPathName, &findStruct); + } while ((hFile < 0) && (__threadErrno == EINTR)); + } +#else + hFile = FindFirstFile(__stringVal(aPathName), &findStruct); + if (hFile < 0) { + __threadErrno = __WIN32_ERR(GetLastError()); + } +#endif + if (! hFile || (hFile == (HANDLE)(-1)) || (hFile == INVALID_HANDLE_VALUE)) { + @global(LastErrorNumber) = __mkSmallInteger(__threadErrno); + } else { + FindClose(hFile); + + id = __mkSmallInteger(0); /* could get it by opening ... */ + size = __MKLARGEINT64(1, findStruct.nFileSizeLow, findStruct.nFileSizeHigh); + + if (findStruct.cFileName[0] != '\0') { + bcopy(findStruct.cFileName, fileNameBuffer, MAX_PATH); + fileNameBuffer[MAX_PATH] = '\0'; + fileName = __MKSTRING(fileNameBuffer); /* FULL name */ + } + + if (findStruct.cAlternateFileName[0] != '\0') { + bcopy(findStruct.cAlternateFileName, alternativeFileNameBuffer, 14); + alternativeFileNameBuffer[14] = '\0'; + alternativeName = __MKSTRING(alternativeFileNameBuffer); /* DOS name */ + } + + /* + * simulate access bits + */ + if (findStruct.dwFileAttributes & FILE_ATTRIBUTE_READONLY) { + modeBits = 0444; + } else { + modeBits = 0666; + } + + if (findStruct.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + type = @symbol(directory); + modeBits |= 0111; /* executable */ + } else { + type = @symbol(regular); + } + + mode = __mkSmallInteger(modeBits); + + /* + * sigh - convert from stupid time to useful time + */ + FileTimeToLocalFileTime(&findStruct.ftCreationTime, &tempFileTime); + FileTimeToSystemTime(&tempFileTime, &creationTime); + FileTimeToLocalFileTime(&findStruct.ftLastAccessTime, &tempFileTime); + FileTimeToSystemTime(&tempFileTime, &accessTime); + FileTimeToLocalFileTime(&findStruct.ftLastWriteTime, &tempFileTime); + FileTimeToSystemTime(&tempFileTime, &modificationTime); + aYr = __mkSmallInteger(accessTime.wYear); + aMon = __mkSmallInteger(accessTime.wMonth); + aDay = __mkSmallInteger(accessTime.wDay); + aHr = __mkSmallInteger(accessTime.wHour); + aMin = __mkSmallInteger(accessTime.wMinute); + aSec = __mkSmallInteger(accessTime.wSecond); + aMS = __mkSmallInteger(accessTime.wMilliseconds); + + mYr = __mkSmallInteger(modificationTime.wYear); + mMon = __mkSmallInteger(modificationTime.wMonth); + mDay = __mkSmallInteger(modificationTime.wDay); + mHr = __mkSmallInteger(modificationTime.wHour); + mMin = __mkSmallInteger(modificationTime.wMinute); + mSec = __mkSmallInteger(modificationTime.wSecond); + mMS = __mkSmallInteger(modificationTime.wMilliseconds); + + cYr = __mkSmallInteger(creationTime.wYear); + cMon = __mkSmallInteger(creationTime.wMonth); + cDay = __mkSmallInteger(creationTime.wDay); + cHr = __mkSmallInteger(creationTime.wHour); + cMin = __mkSmallInteger(creationTime.wMinute); + cSec = __mkSmallInteger(creationTime.wSecond); + cMS = __mkSmallInteger(creationTime.wMilliseconds); + } } %}. (aPathName endsWith:'.lnk') ifTrue:[ - type := #symbolicLink. - path := self getLinkTarget:aPathName. + type := #symbolicLink. + path := nil. + "/ now done lazyly in FileStatusInfo, when the path is accessed + "/ path := self getLinkTarget:aPathName. ]. mode isNil ifTrue:[ - (self isDirectory:aPathName) ifTrue:[ - "/ the code above fails for root directories (these do not exist). - "/ simulate - mode := 8r777. - type := #directory. - uid := gid := 0. - size := 0. - id := 0. - atime := mtime := ctime := Timestamp now. - ]. + (self isDirectory:aPathName) ifTrue:[ + "/ the code above fails for root directories (these do not exist). + "/ simulate + mode := 8r777. + type := #directory. + uid := gid := 0. + size := 0. + id := 0. + atime := mtime := ctime := Timestamp now. + ]. ]. mode notNil ifTrue:[ - atime isNil ifTrue:[ - atime := Timestamp day:aDay month:aMon year:aYr hour:aHr minutes:aMin seconds:aSec milliseconds:aMS. - ]. - mtime isNil ifTrue:[ - mtime := Timestamp day:mDay month:mMon year:mYr hour:mHr minutes:mMin seconds:mSec milliseconds:mMS. - ]. - ctime isNil ifTrue:[ - ctime := Timestamp day:cDay month:cMon year:cYr hour:cHr minutes:cMin seconds:cSec milliseconds:cMS. - ]. - - info := FileStatusInfo - type:type - mode:mode - uid:uid - gid:gid - size:size - id:id - accessed:atime - modified:mtime - created:ctime - path:path - fullName:fileName - alternativeName:alternativeName. - ^ info + atime isNil ifTrue:[ + atime := Timestamp day:aDay month:aMon year:aYr hour:aHr minutes:aMin seconds:aSec milliseconds:aMS. + ]. + mtime isNil ifTrue:[ + mtime := Timestamp day:mDay month:mMon year:mYr hour:mHr minutes:mMin seconds:mSec milliseconds:mMS. + ]. + ctime isNil ifTrue:[ + ctime := Timestamp day:cDay month:cMon year:cYr hour:cHr minutes:cMin seconds:cSec milliseconds:cMS. + ]. + + info := FileStatusInfo + type:type + mode:mode + uid:uid + gid:gid + size:size + id:id + accessed:atime + modified:mtime + created:ctime + path:path + fullName:fileName + alternativeName:alternativeName. + ^ info ]. ^ nil @@ -4904,7 +4909,7 @@ OperatingSystem linkInfoOf:'C:\Dokumente und Einstellungen\cg\Favoriten\Incoming.lnk' " - "Modified: / 08-11-2006 / 12:20:13 / cg" + "Modified: / 07-02-2007 / 10:30:14 / cg" ! mimeTypeForSuffix:aFileSuffix @@ -9675,8 +9680,16 @@ path "for symbolic links only: return the path where the symbolic link points to" + "/ access lazily... + path isNil ifTrue:[ + type == #symbolicLink ifTrue:[ + path := OperatingSystem getLinkTarget:fullName. + ] + ]. + ^ path + "Modified: / 07-02-2007 / 10:31:56 / cg" ! recordAttributes @@ -12745,7 +12758,7 @@ !Win32OperatingSystem class methodsFor:'documentation'! version - ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.264 2007-01-26 13:34:10 cg Exp $' + ^ '$Header: /cvs/stx/stx/libbasic/Win32OperatingSystem.st,v 1.265 2007-02-07 09:50:22 cg Exp $' ! ! Win32OperatingSystem initialize!