📄 win32.cxx
字号:
/*
* win32.cxx
*
* Miscellaneous implementation of classes for Win32
*
* Portable Windows Library
*
* Copyright (c) 1993-1998 Equivalence Pty. Ltd.
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is Portable Windows Library.
*
* The Initial Developer of the Original Code is Equivalence Pty. Ltd.
*
* Portions are Copyright (C) 1993 Free Software Foundation, Inc.
* All Rights Reserved.
*
* Contributor(s): ______________________________________.
*
* $Revision: 19583 $
* $Author: rjongbloed $
* $Date: 2008-02-22 07:06:42 +0000 (Fri, 22 Feb 2008) $
*/
#include <ptlib.h>
#include <ptlib/pprocess.h>
#include <ptlib/msos/ptlib/debstrm.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#ifdef __MINGW32__
#include <process.h>
#endif
#if defined(_MSC_VER) && !defined(_WIN32_WCE)
#include <process.h>
#pragma comment(lib, "mpr.lib")
#endif
#if defined(_WIN32_DCOM)
#include <objbase.h>
#ifdef _MSC_VER
#pragma comment(lib, _OLE_LIB)
#endif
#endif
#include "../common/pglobalstatic.cxx"
#define new PNEW
///////////////////////////////////////////////////////////////////////////////
// PTime
PTime::PTime()
{
// Magic constant to convert epoch from 1601 to 1970
static const PInt64 delta = ((PInt64)369*365+(369/4)-3)*24*60*60U;
static const PInt64 scale = 10000000;
PInt64 timestamp;
#ifndef _WIN32_WCE
GetSystemTimeAsFileTime((LPFILETIME)×tamp);
#else
SYSTEMTIME SystemTime;
GetSystemTime(&SystemTime);
SystemTimeToFileTime(&SystemTime, (LPFILETIME)×tamp);
#endif
theTime = (time_t)(timestamp/scale - delta);
microseconds = (long)(timestamp%scale/10);
}
#ifdef UNICODE
static void PWIN32GetLocaleInfo(LCID Locale,LCTYPE LCType,LPSTR lpLCData,int cchData)
{
TCHAR* pw = new TCHAR[cchData+1];
GetLocaleInfo(Locale,LCType,pw,cchData);
lpLCData[0]=0;
WideCharToMultiByte(GetACP(), 0, pw, -1, lpLCData, cchData, NULL, NULL);
}
#else
#define PWIN32GetLocaleInfo GetLocaleInfo
#endif
PString PTime::GetTimeSeparator()
{
PString str;
PWIN32GetLocaleInfo(GetUserDefaultLCID(), LOCALE_STIME, str.GetPointer(100), 99);
str.MakeMinimumSize();
return str;
}
PBoolean PTime::GetTimeAMPM()
{
char str[2];
PWIN32GetLocaleInfo(GetUserDefaultLCID(), LOCALE_ITIME, str, sizeof(str));
return str[0] == '0';
}
PString PTime::GetTimeAM()
{
PString str;
PWIN32GetLocaleInfo(GetUserDefaultLCID(), LOCALE_S1159, str.GetPointer(100), 99);
str.MakeMinimumSize();
return str;
}
PString PTime::GetTimePM()
{
PString str;
PWIN32GetLocaleInfo(GetUserDefaultLCID(), LOCALE_S2359, str.GetPointer(100), 99);
str.MakeMinimumSize();
return str;
}
PString PTime::GetDayName(Weekdays dayOfWeek, NameType type)
{
PString str;
// Of course Sunday is 6 and Monday is 1...
PWIN32GetLocaleInfo(GetUserDefaultLCID(), (dayOfWeek+6)%7 +
(type == Abbreviated ? LOCALE_SABBREVDAYNAME1 : LOCALE_SDAYNAME1),
str.GetPointer(100), 99);
str.MakeMinimumSize();
return str;
}
PString PTime::GetDateSeparator()
{
PString str;
PWIN32GetLocaleInfo(GetUserDefaultLCID(), LOCALE_SDATE, str.GetPointer(100), 99);
str.MakeMinimumSize();
return str;
}
PString PTime::GetMonthName(Months month, NameType type)
{
PString str;
PWIN32GetLocaleInfo(GetUserDefaultLCID(), month-1 +
(type == Abbreviated ? LOCALE_SABBREVMONTHNAME1 : LOCALE_SMONTHNAME1),
str.GetPointer(100), 99);
str.MakeMinimumSize();
return str;
}
PTime::DateOrder PTime::GetDateOrder()
{
char str[2];
PWIN32GetLocaleInfo(GetUserDefaultLCID(), LOCALE_IDATE, str, sizeof(str));
return (DateOrder)(str[0] - '0');
}
PBoolean PTime::IsDaylightSavings()
{
TIME_ZONE_INFORMATION tz;
DWORD result = GetTimeZoneInformation(&tz);
PAssertOS(result != 0xffffffff);
return result == TIME_ZONE_ID_DAYLIGHT;
}
int PTime::GetTimeZone(TimeZoneType type)
{
TIME_ZONE_INFORMATION tz;
PAssertOS(GetTimeZoneInformation(&tz) != 0xffffffff);
if (type == DaylightSavings)
tz.Bias += tz.DaylightBias;
return -tz.Bias;
}
PString PTime::GetTimeZoneString(TimeZoneType type)
{
TIME_ZONE_INFORMATION tz;
PAssertOS(GetTimeZoneInformation(&tz) != 0xffffffff);
return (const wchar_t *)(type == StandardTime ? tz.StandardName : tz.DaylightName);
}
///////////////////////////////////////////////////////////////////////////////
// PTimeInterval
static unsigned GetDivisor()
{
LARGE_INTEGER frequency;
if (QueryPerformanceFrequency(&frequency))
return (unsigned)frequency.QuadPart/1000;
return 0;
}
PTimeInterval PTimer::Tick()
{
static unsigned divisor = GetDivisor();
if (divisor == 0)
return (int)(GetTickCount()&0x7fffffff);
LARGE_INTEGER count;
QueryPerformanceCounter(&count);
return count.QuadPart/divisor;
}
unsigned PTimer::Resolution()
{
LARGE_INTEGER frequency;
if (QueryPerformanceFrequency(&frequency) && frequency.QuadPart >= 1000)
return 1;
#ifndef _WIN32_WCE
DWORD err = GetLastError();
DWORD timeAdjustment;
DWORD timeIncrement;
BOOL timeAdjustmentDisabled;
if (GetSystemTimeAdjustment(&timeAdjustment, &timeIncrement, &timeAdjustmentDisabled))
return timeIncrement/10000;
err = GetLastError();
#endif
return 55;
}
///////////////////////////////////////////////////////////////////////////////
// Directories
void PDirectory::Construct()
{
hFindFile = INVALID_HANDLE_VALUE;
fileinfo.cFileName[0] = '\0';
PCaselessString::AssignContents(CreateFullPath(*this, PTrue));
}
void PDirectory::CopyContents(const PDirectory & dir)
{
scanMask = dir.scanMask;
hFindFile = INVALID_HANDLE_VALUE;
fileinfo = dir.fileinfo;
}
PBoolean PDirectory::Open(int newScanMask)
{
scanMask = newScanMask;
PVarString wildcard = *this + "*.*";
hFindFile = FindFirstFile(wildcard, &fileinfo);
if (hFindFile == INVALID_HANDLE_VALUE)
return PFalse;
return Filtered() ? Next() : PTrue;
}
PBoolean PDirectory::Next()
{
if (hFindFile == INVALID_HANDLE_VALUE)
return PFalse;
do {
if (!FindNextFile(hFindFile, &fileinfo))
return PFalse;
} while (Filtered());
return PTrue;
}
PCaselessString PDirectory::GetEntryName() const
{
return fileinfo.cFileName;
}
PBoolean PDirectory::IsSubDir() const
{
return (fileinfo.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) != 0;
}
PCaselessString PDirectory::GetVolume() const
{
#ifdef _WIN32_WCE
return PCaselessString("\\");
#else
char volName[100];
PAssertOS(GetVolumeInformation(NULL, volName, sizeof(volName), NULL, NULL, NULL, NULL, 0));
return PCaselessString(volName);
#endif
}
void PDirectory::Close()
{
if (hFindFile != INVALID_HANDLE_VALUE) {
FindClose(hFindFile);
hFindFile = INVALID_HANDLE_VALUE;
}
}
PString PDirectory::CreateFullPath(const PString & path, PBoolean isDirectory)
{
if (path.IsEmpty() && !isDirectory)
return path;
#ifdef _WIN32_WCE //doesn't support Current Directory so the path suppose to be full
PString fullpath=path;
PINDEX len = fullpath.GetLength();
#else
PString partialpath = path;
// Look for special case of "\c:\" at start of string as some generalised
// directory processing algorithms have a habit of adding a leading
// PDIR_SEPARATOR as it would be for Unix.
if (partialpath.NumCompare("\\\\\\") == EqualTo ||
(partialpath.GetLength() > 3 &&
partialpath[0] == PDIR_SEPARATOR &&
partialpath[2] == ':'))
partialpath.Delete(0, 1);
LPSTR dummy;
PString fullpath;
PINDEX len = (PINDEX)GetFullPathName(partialpath,
_MAX_PATH, fullpath.GetPointer(_MAX_PATH), &dummy);
#endif
if (isDirectory && len > 0 && fullpath[len-1] != PDIR_SEPARATOR)
fullpath += PDIR_SEPARATOR;
PINDEX pos = 0;
while ((pos = fullpath.Find('/', pos)) != P_MAX_INDEX)
fullpath[pos] = PDIR_SEPARATOR;
return fullpath;
}
typedef PBoolean (WINAPI *GetDiskFreeSpaceExType)(LPCTSTR lpDirectoryName,
PULARGE_INTEGER lpFreeBytesAvailableToCaller,
PULARGE_INTEGER lpTotalNumberOfBytes,
PULARGE_INTEGER lpTotalNumberOfFreeBytes);
PBoolean PDirectory::GetVolumeSpace(PInt64 & total, PInt64 & free, DWORD & clusterSize) const
{
clusterSize = 512;
total = free = ULONG_MAX;
PString root;
if ((*this)[1] == ':')
root = Left(3);
else if (theArray[0] == '\\' && theArray[1] == '\\') {
PINDEX backslash = Find('\\', 2);
if (backslash != P_MAX_INDEX) {
backslash = Find('\\', backslash+1);
if (backslash != P_MAX_INDEX)
root = Left(backslash+1);
}
}
if (root.IsEmpty())
return PFalse;
#ifndef _WIN32_WCE
PBoolean needTotalAndFree = PTrue;
static GetDiskFreeSpaceExType GetDiskFreeSpaceEx =
(GetDiskFreeSpaceExType)GetProcAddress(LoadLibrary("KERNEL32.DLL"), "GetDiskFreeSpaceExA");
if (GetDiskFreeSpaceEx != NULL) {
ULARGE_INTEGER freeBytesAvailableToCaller;
ULARGE_INTEGER totalNumberOfBytes;
ULARGE_INTEGER totalNumberOfFreeBytes;
if (GetDiskFreeSpaceEx(root,
&freeBytesAvailableToCaller,
&totalNumberOfBytes,
&totalNumberOfFreeBytes)) {
total = totalNumberOfBytes.QuadPart;
free = totalNumberOfFreeBytes.QuadPart;
needTotalAndFree = PFalse;
}
}
clusterSize = 0;
char fsName[100];
if (GetVolumeInformation(root, NULL, 0, NULL, NULL, NULL, fsName, sizeof(fsName))) {
if (strcasecmp(fsName, "FAT32") == 0) {
clusterSize = 4096; // Cannot use GetDiskFreeSpace() results for FAT32
if (!needTotalAndFree)
return PTrue;
}
}
DWORD sectorsPerCluster; // address of sectors per cluster
DWORD bytesPerSector; // address of bytes per sector
DWORD numberOfFreeClusters; // address of number of free clusters
DWORD totalNumberOfClusters; // address of total number of clusters
if (!GetDiskFreeSpace(root,
§orsPerCluster,
&bytesPerSector,
&numberOfFreeClusters,
&totalNumberOfClusters))
{
if (root[0] != '\\' || ::GetLastError() != ERROR_NOT_SUPPORTED)
return PFalse;
PString drive = "A:";
while (WNetAddConnection(root, NULL, drive) != NO_ERROR) {
if (GetLastError() != ERROR_ALREADY_ASSIGNED)
return PFalse;
drive[0]++;
}
PBoolean ok = GetDiskFreeSpace(drive+'\\',
§orsPerCluster,
&bytesPerSector,
&numberOfFreeClusters,
&totalNumberOfClusters);
WNetCancelConnection(drive, PTrue);
if (!ok)
return PFalse;
}
if (needTotalAndFree) {
free = numberOfFreeClusters*sectorsPerCluster*bytesPerSector;
total = totalNumberOfClusters*sectorsPerCluster*bytesPerSector;
}
if (clusterSize == 0)
clusterSize = bytesPerSector*sectorsPerCluster;
return PTrue;
#elif _WIN32_WCE < 300
USES_CONVERSION;
ULARGE_INTEGER freeBytesAvailableToCaller;
ULARGE_INTEGER totalNumberOfBytes;
ULARGE_INTEGER totalNumberOfFreeBytes;
if (GetDiskFreeSpaceEx(A2T(root),
&freeBytesAvailableToCaller,
&totalNumberOfBytes,
&totalNumberOfFreeBytes))
{
total = totalNumberOfBytes.QuadPart;
free = totalNumberOfFreeBytes.QuadPart;
clusterSize = 512; //X3
return PTrue;
}
return PFalse;
#else
return PFalse;
#endif
}
///////////////////////////////////////////////////////////////////////////////
// PFilePath
static PString IllegalFilenameCharacters =
"\\/:*?\"<>|"
"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\0x10"
"\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f";
PBoolean PFilePath::IsValid(char c)
{
return IllegalFilenameCharacters.Find(c) == P_MAX_INDEX;
}
PBoolean PFilePath::IsValid(const PString & str)
{
return str != "." && str != ".." &&
str.FindOneOf(IllegalFilenameCharacters) == P_MAX_INDEX;
}
///////////////////////////////////////////////////////////////////////////////
// PChannel
PString PChannel::GetErrorText(Errors lastError, int osError)
{
if (osError == 0) {
if (lastError == NoError)
return PString();
static int const errors[NumNormalisedErrors] = {
0, ENOENT, EEXIST, ENOSPC, EACCES, EBUSY, EINVAL, ENOMEM, EBADF, EAGAIN, EINTR,
WSAEMSGSIZE|PWIN32ErrorFlag, EIO, 0x1000000|PWIN32ErrorFlag
};
osError = errors[lastError];
}
#ifndef _WIN32_WCE
if (osError > 0 && osError < _sys_nerr && _sys_errlist[osError][0] != '\0')
return _sys_errlist[osError];
#endif
if ((osError & PWIN32ErrorFlag) == 0)
return psprintf("C runtime error %u", osError);
DWORD err = osError & ~PWIN32ErrorFlag;
static const struct {
DWORD id;
const char * msg;
} win32_errlist[] = {
{ ERROR_FILE_NOT_FOUND, "File not found" },
{ ERROR_PATH_NOT_FOUND, "Path not found" },
{ ERROR_ACCESS_DENIED, "Access denied" },
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -