📄 win32.cxx
字号:
*
* Revision 1.13 1996/01/28 02:56:56 robertj
* Fixed bug in PFilePath functions for if path ends in a directory separator.
* Made sure all directory separators are correct character in normalised path.
*
* Revision 1.12 1996/01/23 13:25:21 robertj
* Added time zones.
* Fixed bug if daylight savings indication.
*
* Revision 1.11 1996/01/02 12:58:33 robertj
* Fixed copy of directories.
* Changed process construction mechanism.
* Made service process "common".
*
* Revision 1.10 1995/12/10 12:05:48 robertj
* Changes to main() startup mechanism to support Mac.
* Moved error code for specific WIN32 and MS-DOS versions.
* Added WIN32 registry support for PConfig objects.
* Added asserts in WIN32 semaphores.
*
* Revision 1.9 1995/11/21 11:53:24 robertj
* Added timeout on semaphore wait.
*
* Revision 1.8 1995/10/14 15:13:04 robertj
* Fixed bug in WIN32 service command line parameters.
*
* Revision 1.7 1995/08/24 12:42:33 robertj
* Changed PChannel so not a PContainer.
* Rewrote PSerialChannel::Read yet again so can break out of I/O.
*
* Revision 1.6 1995/07/02 01:26:52 robertj
* Changed thread internal variables.
* Added service process support for NT.
*
* Revision 1.5 1995/06/17 01:03:08 robertj
* Added NT service process type.
*
* Revision 1.4 1995/06/04 12:48:52 robertj
* Fixed bug in directory path creation.
* Fixed bug in comms channel open error.
*
* Revision 1.3 1995/04/25 11:33:54 robertj
* Fixed Borland compiler warnings.
*
* Revision 1.2 1995/03/22 13:56:18 robertj
* Fixed directory handle value check for closing directory.
*
// Revision 1.1 1995/03/14 12:45:20 robertj
// Initial revision
//
*/
#include <ptlib.h>
#include <process.h>
#include <ptlib/msos/ptlib/debstrm.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#ifndef _WIN32_WCE
#ifdef _MSC_VER
#pragma comment(lib, "mpr.lib")
#endif
#endif
#define new PNEW
#if defined(_WIN32_DCOM)
#include <objbase.h>
#ifdef _MSC_VER
#pragma comment(lib, _OLE_LIB)
#endif
#endif
#include "../common/pglobalstatic.cxx"
///////////////////////////////////////////////////////////////////////////////
// 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;
}
BOOL 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');
}
BOOL 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 WORD *)(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;
DWORD err = GetLastError();
#ifndef _WIN32_WCE
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, TRUE));
}
void PDirectory::CopyContents(const PDirectory & dir)
{
scanMask = dir.scanMask;
hFindFile = INVALID_HANDLE_VALUE;
fileinfo = dir.fileinfo;
}
BOOL PDirectory::Open(int newScanMask)
{
scanMask = newScanMask;
#ifdef UNICODE
USES_CONVERSION;
hFindFile = FindFirstFile(A2T(operator+("*.*")), &fileinfo);
#else
hFindFile = FindFirstFile(operator+("*.*"), &fileinfo);
#endif
if (hFindFile == INVALID_HANDLE_VALUE)
return FALSE;
return Filtered() ? Next() : TRUE;
}
BOOL PDirectory::Next()
{
if (hFindFile == INVALID_HANDLE_VALUE)
return FALSE;
do {
if (!FindNextFile(hFindFile, &fileinfo))
return FALSE;
} while (Filtered());
return TRUE;
}
PCaselessString PDirectory::GetEntryName() const
{
return fileinfo.cFileName;
}
BOOL 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, BOOL 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 BOOL (WINAPI *GetDiskFreeSpaceExType)(LPCTSTR lpDirectoryName,
PULARGE_INTEGER lpFreeBytesAvailableToCaller,
PULARGE_INTEGER lpTotalNumberOfBytes,
PULARGE_INTEGER lpTotalNumberOfFreeBytes);
BOOL 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 FALSE;
#ifndef _WIN32_WCE
BOOL needTotalAndFree = TRUE;
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 = FALSE;
}
}
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 TRUE;
}
}
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 FALSE;
PString drive = "A:";
while (WNetAddConnection(root, NULL, drive) != NO_ERROR) {
if (GetLastError() != ERROR_ALREADY_ASSIGNED)
return FALSE;
drive[0]++;
}
BOOL ok = GetDiskFreeSpace(drive+'\\',
§orsPerCluster,
&bytesPerSector,
&numberOfFreeClusters,
&totalNumberOfClusters);
WNetCancelConnection(drive, TRUE);
if (!ok)
return FALSE;
}
if (needTotalAndFree) {
free = numberOfFreeClusters*sectorsPerCluster*bytesPerSector;
total = totalNumberOfClusters*sectorsPerCluster*bytesPerSector;
}
if (clusterSize == 0)
clusterSize = bytesPerSector*sectorsPerCluster;
return TRUE;
#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 TRUE;
}
return FALSE;
#else
return FALSE;
#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";
BOOL PFilePath::IsValid(char c)
{
return IllegalFilenameCharacters.Find(c) == P_MAX_INDEX;
}
BOOL 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) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -