HP-Socket学习02 Windows

  • GetVersionEx

[GetVersionEx可能被修改或无法在windows8.1之后发布。相反,使用Version Helper函数]

随着Windows 8.1的发布,GetVersionEx API的行为在它将返回操作系统版本的值中发生了变化。GetVersionEx函数返回的值现在取决于应用程序的表示方式。

Windows 8.1或Windows 10中未显示的应用程序将返回Windows 8 OS版本值(6.2)。一旦应用程序显示为给定的操作系统版本,GetVersionEx将始终返回应用程序显示为未来版本的版本。要为windows8.1或windows10显示您的应用程序,请参阅针对Windows的应用程序。

确定当前操作系统通常不是确定某个操作系统特性是否存在的最佳方法。这是因为操作系统可能在可重新发布的DLL中添加了新特性。与其使用GetVersionEx来确定操作系统平台或版本号,不如测试该特性本身的存在性。有关更多信息,请参阅操作系统版本。

GetSystemMetrics函数提供关于当前操作系统的附加信息。

要检查特定的操作系统或操作系统特性,请使用IsOS函数。GetProductInfo函数检索产品类型。

要检索远程计算机上操作系统的信息,请使用NetWkstaGetInfo函数、Win32_OperatingSystem WMI类或IADsComputer接口的OperatingSystem属性。

要将当前系统版本与所需版本进行比较,请使用VerifyVersionInfo函数,而不是使用GetVersionEx自己执行比较。

如果兼容模式有效,GetVersionEx函数将报告其标识的操作系统(可能不是安装的操作系统)。例如,如果兼容模式有效,GetVersionEx将报告为应用程序兼容性选择的操作系统。

https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getversionexa

https://docs.microsoft.com/zh-cn/windows/desktop/SysInfo/version-helper-apis

  • 单例
template<class T>
class CSingleObject
{
public:
	CSingleObject	()	{T::CreateInstance();}
	~CSingleObject	()	{T::DeleteInstance();}
	T* GetPointer	()	{return T::GetThis();}
	T& GetObject	()	{return T::GetInstance();}
	BOOL IsValid	()	{return GetPointer() != nullptr;}
};

Singleton.h中宏感觉挺有意思的:


#define SINGLETON_THIS(ClassName)		ClassName::GetThis()
#define SINGLETON_INSTANCE(ClassName)	ClassName::GetInstance()
#define SINGLETON_OBJECT(ObjName)		SINGLETON_INSTANCE(C##ObjName)

#define DEFINE_SINGLETON(ClassName)											\
	ClassName* ClassName::m_pThis = nullptr;

#define DEFINE_P_THIS(ClassName)											\
		DEFINE_SINGLETON(ClassName)

#define DECLARE_SINGLETON_INTERFACE(ClassName)								\
public:																		\
	static ClassName* GetThis()		{return m_pThis;}						\
	static ClassName& GetInstance() {return *m_pThis;}						\
protected:																	\
	static ClassName* m_pThis;

#define DECLARE_SINGLETON_CREATE_INSTANCE(ClassName)						\
public:																		\
	static BOOL CreateInstance()											\
	{																		\
		if(!m_pThis)														\
			m_pThis = new ClassName;										\
																			\
		return m_pThis != nullptr;											\
	}																		\
																			\
	static BOOL DeleteInstance()											\
	{																		\
		if(m_pThis)															\
		{																	\
			delete m_pThis;													\
			m_pThis = nullptr;												\
		}																	\
																			\
		return m_pThis == nullptr;											\
	}

#define DECLARE_PRIVATE_DEFAULT_CONSTRUCTOR(ClassName)						\
private:																	\
	ClassName(){}

#define DECLARE_PRIVATE_COPY_CONSTRUCTOR(ClassName)							\
private:																	\
	ClassName(const ClassName&);											\
	ClassName& operator = (const ClassName&);

#define DECLARE_NO_COPY_CLASS(className)									\
		DECLARE_PRIVATE_COPY_CONSTRUCTOR(className)


#define DECLARE_SINGLETON_IMPLEMENT_NO_CREATE_INSTANCE(ClassName)			\
	DECLARE_SINGLETON_INTERFACE(ClassName)									\
	DECLARE_PRIVATE_DEFAULT_CONSTRUCTOR(ClassName)							\
	DECLARE_PRIVATE_COPY_CONSTRUCTOR(ClassName)								

#define DECLARE_SINGLETON_IMPLEMENT_NO_DEFAULT_CONSTRUCTOR(ClassName)		\
	DECLARE_SINGLETON_CREATE_INSTANCE(ClassName)							\
	DECLARE_PRIVATE_COPY_CONSTRUCTOR(ClassName)

#define DECLARE_SINGLETON_IMPLEMENT(ClassName)								\
	DECLARE_SINGLETON_IMPLEMENT_NO_DEFAULT_CONSTRUCTOR(ClassName)			\
	DECLARE_PRIVATE_DEFAULT_CONSTRUCTOR(ClassName)

#define DECLARE_SINGLETON_NO_DEFAULT_CONSTRUCTOR(ClassName)					\
	DECLARE_SINGLETON_INTERFACE(ClassName)									\
	DECLARE_SINGLETON_IMPLEMENT_NO_DEFAULT_CONSTRUCTOR(ClassName)

#define DECLARE_SINGLETON(ClassName)										\
	DECLARE_SINGLETON_NO_DEFAULT_CONSTRUCTOR(ClassName)						\
	DECLARE_PRIVATE_DEFAULT_CONSTRUCTOR(ClassName)

#define DECLARE_SINGLE_OBJECT(ClassName) CSingleObject<ClassName> _##ClassName##_Single_Object_;

SRWLOCK

SRWLOCK对象析构时系统会自动清理读写锁
Initialize a slim reader/writer (SRW) lock.
void InitializeSRWLock(
  PSRWLOCK SRWLock
);

Acquires a slim reader/writer (SRW) lock in exclusive mode.
获取排他模式下的瘦读/写锁(SRW)。
void AcquireSRWLockExclusive(
  PSRWLOCK SRWLock
);


Acquires a slim reader/writer (SRW) lock in shared mode.
获取共享模式下的瘦读/写锁(SRW)。
void AcquireSRWLockShared(
  PSRWLOCK SRWLock
);

Releases a slim reader/writer (SRW) lock that was acquired in shared mode.
void ReleaseSRWLockShared(
  PSRWLOCK SRWLock
);

Releases a slim reader/writer (SRW) lock that was acquired in exclusive mode.
void ReleaseSRWLockExclusive(
  PSRWLOCK SRWLock
);

Attempts to acquire a slim reader/writer (SRW) lock in shared mode. If the call is successful, the calling thread takes ownership of the lock.
BOOLEAN TryAcquireSRWLockShared(
  PSRWLOCK SRWLock
);

Attempts to acquire a slim reader/writer (SRW) lock in exclusive mode. If the call is successful, the calling thread takes ownership of the lock.
BOOLEAN TryAcquireSRWLockExclusive(
  PSRWLOCK SRWLock
);

自旋锁

定义:
template<class CLockObj> class CLocalLock
{
public:
	CLocalLock(CLockObj& obj) : m_lock(obj) {m_lock.Lock();}
	~CLocalLock() {m_lock.Unlock();}
private:
	CLockObj& m_lock;
};


typedef CLocalLock<CSpinGuard>				CSpinLock;

class CSpinGuard
{
public:
	CSpinGuard() : m_lFlag(0)
	{

	}

	~CSpinGuard()
	{
		ASSERT(m_lFlag == 0);
	}

	void Lock()
	{
		for(UINT i = 0; !TryLock(); ++i)
			YieldThread(i);
	}

	BOOL TryLock()
	{
		if(::InterlockedCompareExchange(&m_lFlag, 1, 0) == 0)
		{
			::_ReadWriteBarrier();
			return TRUE;
		}

		return FALSE;
	}

	void Unlock()
	{
		ASSERT(m_lFlag == 1);
		m_lFlag = 0;
	}

private:
	CSpinGuard(const CSpinGuard& cs);
	CSpinGuard operator = (const CSpinGuard& cs);

private:
	volatile LONG m_lFlag;
};
使用:
VOID CSlimRWLock::WaitToRead()
{
	BOOL bWait = FALSE;

	{
                //使用自旋锁
		CSpinLock locallock(m_cs);

		if(m_nActive > 0)
			++m_nActive;
		else if(m_nActive == 0)
		{
			if(m_smLock.TryWaitToRead())
			{
				++m_nReadCount;
				++m_nActive;
			}
			else
				bWait = TRUE;
		}
		else if(!IsOwner())
			bWait = TRUE;
	}

	if(bWait)
	{
		m_smLock.WaitToRead();

		CSpinLock locallock(m_cs);
		{
			++m_nReadCount;
			++m_nActive;
		}
	}
}

_WIN32_WINNT版本列表

#define _WIN32_WINNT_NT4                    0x0400 // Windows NT 4.0 
#define _WIN32_WINNT_WIN2K                  0x0500 // Windows 2000 #define _WIN32_WINNT_WINXP                  0x0501 // Windows XP 
#define _WIN32_WINNT_WS03                   0x0502 // Windows Server 2003 
#define _WIN32_WINNT_WIN6                   0x0600 // Windows Vista 
#define _WIN32_WINNT_VISTA                  0x0600 // Windows Vista 
#define _WIN32_WINNT_WS08                   0x0600 // Windows Server 2008 
#define _WIN32_WINNT_LONGHORN               0x0600 // Windows Vista 
#define _WIN32_WINNT_WIN7                   0x0601 // Windows 7 
#define _WIN32_WINNT_WIN8                   0x0602 // Windows 8 
#define _WIN32_WINNT_WINBLUE                0x0603 // Windows 8.1 
#define _WIN32_WINNT_WINTHRESHOLD           0x0A00 // Windows 10 
#define _WIN32_WINNT_WIN10                  0x0A00 // Windows 10

原文:https://blog.csdn.net/cai6811376/article/details/52637728 

信号量

创建或打开一个已命名或未命名的信号量对象。
要为对象指定访问掩码,请使用CreateSemaphoreEx函数。
HANDLE CreateSemaphoreW(
  LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,   //安全描述符 如果该参数为NULL,则子进程无法继承信号量句柄。如果该参数为NULL,信号量将获得默认的安全描述符。
信号量的默认安全描述符中的acl来自创建者的主令牌或模拟令牌。 
  LONG                  lInitialCount,            //信号量对象的初始计数。这个值必须大于或等于0,小于或等于lMaximumCount。
信号量的状态在其计数大于0时发出信号,在其计数为0时发出无信号。
每当等待函数释放正在等待信号量的线程时,计数就会减少1。通过调用ReleaseSemaphore函数,将计数增加指定的数量。
  LONG                  lMaximumCount,            //信号量对象的最大计数。这个值必须大于零。
  LPCWSTR               lpName                    //指向一个以null结尾的字符串的指针,该字符串指定信号量对象的名称。名称仅限于MAX_PATH字符。名称比较是区分大小写的。
如果lpName匹配现有的已命名信号量对象的名称,则忽略lInitialCount和lMaximumCount参数,因为它们已经由创建进程设置。
如果lpSemaphoreAttributes参数不是NULL,它将确定句柄是否可以继承。
如果lpName为NULL,则在没有名称的情况下创建信号量对象。
如果lpName匹配现有事件、互斥锁、等待计时器、作业或文件映射对象的名称,则函数失败,GetLastError函数返回ERROR_INVALID_HANDLE。这是因为这些对象共享相同的名称空间。
);
返回值:
如果函数成功,返回值就是信号量对象的句柄。如果指定的信号量对象在函数调用之前已经存在,那么函数将返回现有对象的句柄,GetLastError将返回ERROR_ALREADY_EXISTS。
如果函数失败,返回值为NULL。要获得扩展的错误信息,请调用GetLastError。

创建或打开一个已命名或未命名的信号量对象,并返回该对象的句柄。
HANDLE CreateSemaphoreExW(
  LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,    
  LONG                  lInitialCount,
  LONG                  lMaximumCount,
  LPCWSTR               lpName,
  DWORD                 dwFlags,                   //此参数是保留的,必须为0。
  DWORD                 dwDesiredAccess            //信号量对象的访问掩码。有关访问权限的列表,请参见同步对象安全性和访问权限。
);

打开一个现有的命名信号量对象。
HANDLE OpenSemaphoreW(
  DWORD   dwDesiredAccess,    //对信号量对象的访问。如果指定对象的安全描述符不允许调用进程访问所请求的访问,则该函数失败。有关访问权限的列表,请参见同步对象安全性和访问权限。
  BOOL    bInheritHandle,    //如果该值为真,则由该流程创建的流程将继承句柄。否则,进程不会继承此句柄。
  LPCWSTR lpName            //要打开的信号量的名称。名称比较是区分大小写的。
这个函数可以在私有命名空间中打开对象。有关更多信息,请参见对象名称空间。
终端服务:名称可以具有“全局”或“本地”前缀,以显式地在全局或会话名称空间中打开对象。名称的其余部分可以包含除反斜杠字符()之外的任何字符。有关更多信息,请参见内核对象名称空间。
注意,快速用户切换是使用终端服务会话实现的。第一个登录的用户使用会话0,下一个登录的用户使用会话1,依此类推。内核对象名称必须遵循终端服务的指导方针,以便应用程序能够支持多个用户。
);
返回值
如果函数成功,返回值就是信号量对象的句柄。
如果函数失败,返回值为NULL。要获得扩展的错误信息,请调用GetLastError。

GetFileAttributesEx

检索指定文件或目录的属性。
要将此操作作为事务操作执行,请使用GetFileAttributesTransacted函数。
BOOL GetFileAttributesExA(
  LPCSTR                 lpFileName,
  GET_FILEEX_INFO_LEVELS fInfoLevelId,    //要检索的属性信息的类。该参数可以是GET_FILEEX_INFO_LEVELS枚举中的以下值。GetFileExInfoStandard
  LPVOID                 lpFileInformation//指向接收属性信息的缓冲区的指针。
存储在这个缓冲区中的属性信息的类型由fInfoLevelId的值决定。
);

eg:
if (GetFileAttributesEx(strPath, GetFileExInfoStandard, &fad))
 unsigned __int64 size += ((ULONG64)fad.nFileSizeHigh & 0xffffffff) << 32 | (ULONG64)fad.nFileSizeLow;//size为文件大小

StrCmpNI

使用C运行时(ASCII)排序规则比较两个字符串开头的指定字符数。比较不区分大小写。
int StrCmpNICW(
  LPCWSTR pszStr1,//指向要比较的第一个以空结束的字符串的指针。
  LPCWSTR pszStr2,//指向要比较的第二个以空结束的字符串的指针。
  int     nChar//要比较的每个字符串开头的字符数。
);

如果子字符串相同,则返回0。如果从pszStr1指向的字符串中获取的字符串按字母顺序大于从pszStr2指向的字符串,则返回正值。如果从pszStr1指向的字符串中获取的字符串按字母顺序小于从pszStr2指向的字符串,则返回一个负值。

GetDiskFreeSpaceExA

检索关于磁盘卷上可用空间总量的信息,可用空间总量是与调用线程相关联的用户可用空间总量、可用空间总量和可用空间总量。
BOOL GetDiskFreeSpaceExA(
  LPCSTR          lpDirectoryName,  //磁盘上的目录。
如果该参数为NULL,则该函数使用当前磁盘的根。
如果这个参数是UNC名称,它必须包含一个后斜杠,例如“\MyServer\MyShare”。
此参数不必指定磁盘上的根目录。该函数接受磁盘上的任何目录。为此,调用应用程序必须具有FILE_LIST_DIRECTORY访问权限 目录中。
  PULARGE_INTEGER lpFreeBytesAvailableToCaller,//指向一个变量的指针,该变量接收与调用线程相关联的用户在磁盘上可用的空闲字节总数。这个参数可以是NULL。
如果每个用户配额正在使用,则此值可能小于磁盘上的空闲字节总数。
  PULARGE_INTEGER lpTotalNumberOfBytes,//指向一个变量的指针,该变量接收与调用线程相关联的用户可用的磁盘上的总字节数。
这个参数可以是NULL。如果每个用户配额正在使用,则此值可能小于磁盘上的总字节数。
要确定磁盘或卷上的总字节数,请使用IOCTL_DISK_GET_LENGTH_INFO。
  PULARGE_INTEGER lpTotalNumberOfFreeBytes//指向接收磁盘上空闲字节总数的变量的指针。
这个参数可以是NULL。
);

如果函数成功,返回值是非零的。
如果函数失败,返回值为0(0)。要获得扩展的错误信息,请调用GetLastError。

CopyFileEx(sSrc, sDes,CopyProgressRoutine,&stuCopyParam,NULL,0);

https://blog.csdn.net/x_y_q_/article/details/52709474:

#include <iostream>
using namespace std;
int main()
{
    //得出磁盘的可用空间
    DWORD dwTotalClusters;//总的簇
    DWORD dwFreeClusters;//可用的簇
    DWORD dwSectPerClust;//每个簇有多少个扇区
    DWORD dwBytesPerSect;//每个扇区有多少个字节
    BOOL bResult = GetDiskFreeSpace(TEXT("C:"),&dwSectPerClust, &dwBytesPerSect, &dwFreeClusters, &dwTotalClusters);
    if(bResult){
        cout << "使用GetDiskFreeSpace函数获取磁盘空间信息" << endl;
        cout << "总簇数量: " << dwTotalClusters << endl;
        cout << "可用的簇: " << dwFreeClusters << endl;
        cout << "每个簇有多少个扇区: " << dwSectPerClust << endl;
        cout << "每个扇区有多少个字节: " <<  dwBytesPerSect << endl;
        cout << "磁盘总容量: " <<  dwTotalClusters * (DWORD64)dwSectPerClust * (DWORD64)dwBytesPerSect << endl;
        cout << "磁盘空闲容量: " << dwFreeClusters * (DWORD64)dwSectPerClust * (DWORD64)dwBytesPerSect << endl;
    }
    cout << "\n\n" << endl;
 
    DWORD64 qwFreeBytes, qwFreeBytesToCaller, qwTotalBytes;
    bResult = GetDiskFreeSpaceEx(TEXT("C:"), 
	(PULARGE_INTEGER)&qwFreeBytesToCaller, 
	(PULARGE_INTEGER)&qwTotalBytes, 
	(PULARGE_INTEGER)&qwFreeBytes);
    if(bResult){
        cout << "使用GetDiskFreeSpaceEx函数获取磁盘空间信息" << endl;
        cout << "磁盘总容量: " <<  qwTotalBytes << endl;
        cout << "可用的磁盘空闲容量: " << qwFreeBytes << endl;
        cout << "磁盘空闲容量: " << qwFreeBytesToCaller << endl;
    }
    system("pause");
}



eg:
在调用GetDiskFreeSpaceEx()获取磁盘空间时,由于参数是ULARGE_INTEGER(64位整数),所以普通的“加减乘除”并不支持(是没有实现),因此我们采用其他办法来实现,先来看下ULARGE_INTEGER的结构定义:

    typedef union _ULARGE_INTEGER {
      struct {
        DWORD LowPart;
        DWORD HighPart;
      } ;
      struct {
        DWORD LowPart;
        DWORD HighPart;
      } u;
      ULONGLONG QuadPart;
    } ULARGE_INTEGER, *PULARGE_INTEGER;


在一次应用中,需要将返回的空间大小转换成以"GB"为单位的,所以写了这样的宏定义:

#define GB(x) ((x.HighPart << 2) + ((DWORD)x.LowPart) / 1024.0 / 1024.0 / 1024.0)

当然,你也可以选择将x两边加上括号即“#define GB(x) (((x).HighPart << 2) + ((DWORD)(x).LowPart) / 1024.0 / 1024.0 / 1024.0)"
原文:https://blog.csdn.net/joeblackzqq/article/details/7042082 

InitializeConditionVariable

void InitializeConditionVariable(
  PCONDITION_VARIABLE ConditionVariable    //条件变量的指针。
);
初始化条件变量。

线程可以使用SleepConditionVariableCS或SleepConditionVariableSRW函数自动释放锁并进入休眠状态。线程使用WakeConditionVariable或WakeAllConditionVariable函数唤醒。
条件变量是不能跨进程共享的用户模式对象。
条件变量不能移动或复制。流程不能修改对象,而必须将其视为逻辑上不透明的。只使用条件变量函数来管理条件变量。

WakeConditionVariable

唤醒一个线程在等待指定的条件变量。
void WakeConditionVariable(
  PCONDITION_VARIABLE ConditionVariable    //条件变量的指针。
);

WakeAllConditionVariable

void WakeAllConditionVariable(
  PCONDITION_VARIABLE ConditionVariable
);

WakeAllConditionVariable唤醒所有等待的线程,而WakeConditionVariable只唤醒一个线程。唤醒一个线程类似于设置一个自动重置事件,而唤醒所有线程类似于触发一个手动重置事件,但更可靠(有关详细信息,请参见PulseEvent)。

SleepConditionVariableCS

在指定的条件变量上休眠,并将指定的临界区作为原子操作释放。
BOOL SleepConditionVariableCS(
  PCONDITION_VARIABLE ConditionVariable,    //指向条件变量的指针。此变量必须使用InitializeConditionVariable函数初始化。
  PCRITICAL_SECTION   CriticalSection,    //指向临界段对象的指针。在调用SleepConditionVariableCS时,调用方必须准确地输入此临界区一次。
  DWORD               dwMilliseconds    //超时间隔,单位为毫秒。如果超时时间间隔超过,函数将重新获取临界区并返回零。如果dw毫秒为零,函数将测试指定对象的状态并立即返回。如果dw毫秒是无穷大的,则函数的超时间隔不会超时。
);



如果函数成功,返回值是非零的。
如果函数失败或超时间隔超过,则返回值为零。要获得扩展的错误信息,请调用GetLastError。可能的错误代码包括ERROR_TIMEOUT,它指示超时间隔在另一个线程尝试唤醒正在睡眠的线程之前已经过去。

SleepConditionVariableSRW

在指定的条件变量上休眠,并将指定的锁作为原子操作释放。
BOOL SleepConditionVariableSRW(
  PCONDITION_VARIABLE ConditionVariable,    //指向条件变量的指针。此变量必须使用InitializeConditionVariable函数初始化。
  PSRWLOCK            SRWLock,              //一个指向锁的指针。此锁必须以Flags参数指定的方式持有。
  DWORD               dwMilliseconds,       //超时间隔,单位为毫秒。如果间隔超过,函数返回。如果dw毫秒为零,函数将测试指定对象的状态并立即返回。如果dw毫秒是无穷大的,则函数的超时间隔不会超时。
  ULONG               Flags                 //如果该参数是CONDITION_VARIABLE_LOCKMODE_SHARED,则SRW锁处于共享模式。否则,锁将处于独占模式。
);

unordered_set<class>::emplace()

emplace会比push,insert少一次临时对象的开销
感觉有点像std::move

 


版权声明:本文为sinat_36391009原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。