#include "StdAfx.h"

#include <SHLWAPI.H>
#include <locale.h>
#include <aplAggr.h>

#include "resource.h"
#include "aplguiex.h"

//const char* cs_must_enter_value=cs_must_enter_value; - удалить после компиляции

__declspec (dllexport) HICON aplGetButtonIco(int nIndex, bool bTruecolor)
{
	if(m_buttons_il==NULL) 
		return NULL;
	else
		return m_buttons_il->ExtractIcon(nIndex);
}

__declspec (dllexport) HICON aplGetButtonIcoGray(int nIndex, bool bTruecolor)
{
	if (m_buttons_gray_il == NULL)
		return NULL;
	else
		return m_buttons_gray_il->ExtractIcon(nIndex);
}
/*
__declspec (dllexport) HICON aplGetStdIco16(int index)
{
	if(m_PssButtonIL==NULL) return NULL;
	else return m_PssButtonIL->ExtractIcon(index);
}
*/

__declspec (dllexport) bool IsPositive(const TCHAR *buf)
{
	if(buf[0]==_T('-')) return false;
	else return true;
}

__declspec (dllexport) bool IsInteger(const TCHAR *buf)
{
	int i=0;
	while(buf[i]!=0)
	{
		if((buf[i]==_T('-') && i==0) || (buf[i]==_T('+') && i==0))
		{
			i++;
			continue;
		}
		else if(!_isdigit(buf[i])) return false;
		i++;
	}
	return true;
}

__declspec (dllexport) bool IsReal(const TCHAR *buf)
{
	//специальный случай, что e15 = 1.0e15 тоже является числом
	static int DD[5][8] = 
	  // 0   1   2   3   4   5   6   7
	{ // 0   +-  b.  09  .   e   e+- e09     state
		{3,	 3,  4,  3,  4,  7,  7,  7}, // 09    0
		{2,	 2,  0,  4,  0,  0,  0,  0}, // .     1
		{0,	 0,  0,  5,  5,  0,  0,  0}, // e     2
		{1,	 0,  0,  0,  0,  6,  0,  0}, // +-    3
		{0,  0,  0,  1,  1,  0,  0,  1}};// для проверки окончания  4
	if(!buf) return false;
	TCHAR ch, decimal = *localeconv()->decimal_point; // Десятичный разделитель.
	int q=0, s;
	for (int i=0; buf[i]; ++i)
	{
		ch = buf[i];
			 if((ch >= _T('0')) && (ch <= _T('9'))) s = 0;
		else if( ch == decimal )			s = 1;
		else if((ch == _T('e')) || (ch == _T('E')))	s = 2;
		else if((ch == _T('-')) || (ch == _T('+'))) s = 3;
		else return false;
		q = DD[s][q];
		if(q == 0) break;
	}
	return (DD[4][q] != 0);
}

__declspec (dllexport) bool IsRealOrEmpty(const TCHAR *buf)
{
	if(buf==0)return true;
	if(buf[0]==0)return true;
	if(_strlen(buf)==0)return true;
	return IsReal(buf);
}



__declspec (dllexport) bool IsTime(const TCHAR *lpszBuf)
{
	CString buf(lpszBuf);
	int ind;
	if(buf.IsEmpty()) return false;
	
	ind = buf.Find(_T(":"));
	ind = ind>-1?ind:buf.Find(_T("/"));
	ind = ind>-1?ind:buf.Find(_T("\\"));
	ind = ind>-1?ind:buf.Find(_T("="));
	ind = ind>-1?ind:buf.Find(_T("*"));
	ind = ind>-1?ind:buf.Find(_T("`"));
	CString t;
	int i;
	if(ind>0)
	{
		t = buf.Left(ind);
		for(i = 0; i<t.GetLength(); i++)
		{
			if (!_isdigit(t[i]))
				return false;
		}

		buf.TrimLeft(t);
		buf.TrimLeft(_T(":"));
		buf.TrimLeft(_T("/"));
		buf.TrimLeft(_T("\\"));
		buf.TrimLeft(_T("*"));
		buf.TrimLeft(_T("`"));
		buf.TrimLeft(_T("="));
		if(buf.GetLength()!=2) return false;
		for (i=0; i<2; i++)
		{
			if(!_isdigit(buf[i]))
				return false;
		}
		int mins = _atoi(buf);
		if(mins>59) return false;
		return true;
	}
	else
	{
		for(i=0; i<buf.GetLength(); i++)
		{
			if(!_isdigit(buf[i]))
				return false;
		}
		return true;
	}
}

__declspec (dllexport) bool TestCharactValue(CString tstVal, bool bTime, CString &message, bool MessageMode)
{
	if(tstVal.IsEmpty()) return true;

	//проверяем может это ресурс с отклонениями
	//Формат должен быть: Значение+-отклонение либо: Значение+отклонение-отклонение
	int PlusFind, MinusFind, ValInd;
	CString buf, val;
	bool bUseOne = false;
	val = tstVal;
	val.TrimRight();
	val.TrimLeft();
	//проверяем, чтобы небыло слов типа ++10 или --10
	//++
	ValInd = 0;
	do
	{
		PlusFind = val.Find(_T("+"), ValInd);
		if(PlusFind<0) break;
		ValInd = PlusFind+1;
		PlusFind = val.Find(_T("+"), ValInd);
		if(PlusFind<0) break;
		if(PlusFind==ValInd) 
		{
			message =  APL_T("Необходимо ввести значение!");
			if(MessageMode)
				AfxMessageBox(message, MB_OK|MB_ICONSTOP);
			return false;
		}
	}while(true);
	//--
	ValInd = 0;
	do
	{
		PlusFind = val.Find(_T("-"), ValInd);
		if(PlusFind<0) break;
		ValInd = PlusFind+1;
		PlusFind = val.Find(_T("-"), ValInd);
		if(PlusFind<0) break;
		if(PlusFind==ValInd)
		{
			message =  APL_T("Необходимо ввести значение!");
			if(MessageMode)
				AfxMessageBox(message, MB_OK|MB_ICONSTOP);
			return false;
		}
	}while(true);
	ValInd = 0;
	//+-
	PlusFind = val.Find(_T("+"), ValInd); //-V666
	if(PlusFind==0)
	{
		ValInd = PlusFind+1;
		PlusFind = val.Find(_T("-"), ValInd);
		if(PlusFind>-1)
		{
			if(PlusFind==ValInd)
			{
				message =  APL_T("Необходимо ввести значение!");
				if(MessageMode)
					AfxMessageBox(message, MB_OK|MB_ICONSTOP);
				return false;
			}
		}
	}
	//-+
	PlusFind = val.Find(_T("-"), ValInd);
	if(PlusFind==0)
	{
		ValInd = PlusFind+1;
		PlusFind = val.Find(_T("+"), ValInd);
		if(PlusFind>-1)
		{
			if(PlusFind==ValInd)
			{
				message =  APL_T("Необходимо ввести значение!");
				if(MessageMode)
					AfxMessageBox(message, MB_OK|MB_ICONSTOP);
				return false;
			}
		}
	}

	PlusFind = val.Find(_T("+"), 1);
	MinusFind = val.Find(_T("-"), 1); //ищем 
	ValInd = PlusFind>0 ? PlusFind : -1;
	ValInd = MinusFind>0 ? (MinusFind>PlusFind ? (PlusFind>0?PlusFind:MinusFind):MinusFind) : ValInd;
	ValInd = ValInd>-1 ? ValInd : val.GetLength();
	if(!bTime)
	{
		if(ValInd>0 && (val[ValInd-1]==_T('e') || val[ValInd-1]==_T('E')))
			ValInd--;
	}
	if(ValInd>-1)
	{
		buf = val.Left(ValInd);
		if(buf.IsEmpty())
		{
			message =  APL_T("Необходимо ввести значение!");
			if(MessageMode)
				AfxMessageBox(message, MB_OK|MB_ICONSTOP);
			return false;
		}
		if(!bTime)
		{
			if(!IsReal(buf)) 
			{
				message =  APL_T("Необходимо ввести числовое значение!");
				if(MessageMode)
					AfxMessageBox(message, MB_OK|MB_ICONSTOP);
				return false;
			}
		}
		else
		{
			if(!IsTime(buf)) 
			{
				message =  APL_T("Необходимо ввести время в формате \"H:MM\"!");
				if(MessageMode)
					AfxMessageBox(message, MB_OK|MB_ICONSTOP);
				return false;
			}
		}
	}
	if(PlusFind>-1 && MinusFind<0)
	{
		buf = val.Mid(PlusFind+1, val.GetLength()-PlusFind-1);
		if(buf.IsEmpty())
		{
			message =  APL_T("Необходимо указать верхнее отклонение!");
			if(MessageMode)
				AfxMessageBox(message, MB_OK|MB_ICONSTOP);
			return false;
		}
		if(!bTime)
		{
			if(!IsReal(buf)) 
			{
				message = APL_T("Верхнее отклонение должно быть числом!");
				if(MessageMode)
					AfxMessageBox(message, MB_OK|MB_ICONSTOP);
				return false;
			}
		}
		else
		{
			if(!IsTime(buf)) 
			{
				message = APL_T("Верхнее отклонение должно иметь формат \"H:MM\"!");
				if(MessageMode)
					AfxMessageBox(message, MB_OK|MB_ICONSTOP);
				return false;
			}
		}
	}
	if(MinusFind>-1 && PlusFind<0)
	{
		buf = val.Mid(MinusFind+1, val.GetLength()-MinusFind-1);
		if(buf.IsEmpty())
		{
			message =  APL_T("Необходимо указать нижнее отклонение!");
			if(MessageMode)
				AfxMessageBox(message, MB_OK|MB_ICONSTOP);
			return false;
		}
		if(!bTime)
		{
			if(!IsReal(buf)) 
			{
				message =  APL_T("Нижнее отклонение должно быть числом!");
				if(MessageMode)
					AfxMessageBox(message, MB_OK|MB_ICONSTOP);
				return false;
			}
		}
		else
		{
			if(!IsTime(buf)) 
			{
				message =  APL_T("Нижнее отклонение должно иметь формат \"H:MM\"!");
				if(MessageMode)
					AfxMessageBox(message, MB_OK|MB_ICONSTOP);
				return false;
			}
		}
	}
	if(PlusFind>-1 && PlusFind<MinusFind)
	{
		//Необходимо определить верхнее и нижнее отклонение
		buf = val.Mid(PlusFind+1, MinusFind-PlusFind-1);//Верхнее
		if(!bTime)
		{
			if(!IsReal(buf) && !buf.IsEmpty()) 
			{
				message =  APL_T("Верхнее отклонение должно быть числом!");
				if(MessageMode)
					AfxMessageBox(message, MB_OK|MB_ICONSTOP);
				return false;
			}
		}
		else
		{
			if(!IsTime(buf) && !buf.IsEmpty()) 
			{
				message =  APL_T("Верхнее отклонение должно иметь формат \"H:MM\"!");
				if(MessageMode)
					AfxMessageBox(message, MB_OK|MB_ICONSTOP);
				return false;
			}
		}
		buf = val.Mid(MinusFind+1, val.GetLength()-MinusFind-1);//Нижнее
		if(!bTime)
		{
			if(!IsReal(buf) && !buf.IsEmpty()) 
			{
				message =  APL_T("Нижнее отклонение должно быть числом!");
				if(MessageMode)
					AfxMessageBox(message, MB_OK|MB_ICONSTOP);
				return false;
			}
		}
		else
		{
			if(!IsTime(buf) && !buf.IsEmpty()) 
			{
				message =  APL_T("Нижнее отклонение должно иметь формат \"H:MM\"!");
				if(MessageMode)
					AfxMessageBox(message, MB_OK|MB_ICONSTOP);
				return false;
			}
		}
	}
	if(MinusFind>-1 && MinusFind<PlusFind)
	{
		//Необходимо определить верхнее и нижнее отклонение
		buf = val.Mid(MinusFind+1, PlusFind-MinusFind-1);//Нижнее
		if(!bTime)
		{
			if(!IsReal(buf) && !buf.IsEmpty()) 
			{
				message =  APL_T("Нижнее отклонение должно быть числом!");
				if(MessageMode)
					AfxMessageBox(message, MB_OK|MB_ICONSTOP);
				return false;
			}
		}
		else
		{
			if(!IsTime(buf) && !buf.IsEmpty()) 
			{
				message =  APL_T("Нижнее отклонение должно иметь формат \"H:MM\"!");
				if(MessageMode)
					AfxMessageBox(message, MB_OK|MB_ICONSTOP);
				return false;
			}
		}
		buf = val.Mid(PlusFind+1, val.GetLength()-PlusFind-1);//верхнее
		if(!bTime)
		{
			if(!IsReal(buf) && !buf.IsEmpty()) 
			{
				message =  APL_T("Верхнее отклонение должно быть числом!");
				if(MessageMode)
					AfxMessageBox(message, MB_OK|MB_ICONSTOP);
				return false;
			}
		}
		else
		{
			if(!IsTime(buf) && !buf.IsEmpty()) 
			{
				message =  APL_T("Верхнее отклонение должно иметь формат \"H:MM\"!");
				if(MessageMode)
					AfxMessageBox(message, MB_OK|MB_ICONSTOP);
				return false;
			}
		}
	}

	return true;
}

__declspec (dllexport) bool aplIsDigit(const TCHAR* lpszStr)
{
	int i=0;
	while(lpszStr[i]!=0)
	{
		if(!iswdigit(lpszStr[i]))
		{
			if(i==0 && lpszStr[i]!=_T('-'))
				return false;
			else if(i>0)
				return false;
		}
		i++;
	}
	return true;
}

__declspec (dllexport) DWORD GetDllVersion(LPCTSTR lpszDllName)
{
	HINSTANCE hinstDll;
    DWORD dwVersion = 0;
	
    hinstDll = ::LoadLibrary(lpszDllName);
    
    if(hinstDll)
    {
        DLLGETVERSIONPROC pDllGetVersion;
		
        pDllGetVersion = (DLLGETVERSIONPROC) GetProcAddress(hinstDll, "DllGetVersion");
		
		/*Because some DLLs might not implement this function, you
		must test for it explicitly. Depending on the particular 
		DLL, the lack of a DllGetVersion function can be a useful
		indicator of the version.
		*/
        if(pDllGetVersion)
        {
            DLLVERSIONINFO dvi;
            HRESULT hr;
			
            ZeroMemory(&dvi, sizeof(dvi));
            dvi.cbSize = sizeof(dvi);
			
            hr = (*pDllGetVersion)(&dvi);
			
            if(SUCCEEDED(hr))
            {
                dwVersion = PACKVERSION(dvi.dwMajorVersion, dvi.dwMinorVersion);
            }
        }
        
        ::FreeLibrary(hinstDll);
    }
    return dwVersion;
}

__declspec (dllexport) bool GetExePath(HMODULE hModule, CString &buf)
{
	buf.Empty();
	if(hModule==NULL) return false;
	TCHAR *tBuf = new TCHAR[1024];
	GetModuleFileName(hModule, tBuf, 1024);
	buf+=tBuf;
	delete []tBuf;
	if(buf.Find(_T("\\"))>-1)
	{
		buf = buf.Left(buf.ReverseFind(_T('\\'))+1);
	}
	else
		buf.Empty();
	return true;
}

#pragma comment(lib, "User32.lib")

#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>

#define BUFSIZE 256

#define PRODUCT_PROFESSIONAL                    0x00000030
#define VER_SUITE_WH_SERVER                    0x00008000


typedef void (WINAPI *PGNSI)(LPSYSTEM_INFO);
typedef BOOL (WINAPI *PGPI)(DWORD, DWORD, DWORD, DWORD, PDWORD);


__declspec (dllexport) bool GetOSDisplayString( CString &verOS)
{
#undef ___FUNCTION___
#define ___FUNCTION___ "GetOSDisplayString"

	verOS = "???";
	TCHAR pszOS[BUFSIZE];
	OSVERSIONINFOEX osvi;
	SYSTEM_INFO si;
	PGNSI pGNSI;
	PGPI pGPI;
	BOOL bOsVersionInfoEx;
	DWORD dwType;

	ZeroMemory(&si, sizeof(SYSTEM_INFO));
	ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));

	osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
	bOsVersionInfoEx = GetVersionEx((OSVERSIONINFO*) &osvi);

	if(bOsVersionInfoEx == NULL )
	{
		return false;
	}

	// Call GetNativeSystemInfo if supported or GetSystemInfo otherwise.

	pGNSI = (PGNSI) GetProcAddress(
		GetModuleHandle(TEXT("kernel32.dll")), 
		"GetNativeSystemInfo");
	if(NULL != pGNSI)
		pGNSI(&si);
	else GetSystemInfo(&si);

	if ( VER_PLATFORM_WIN32_NT==osvi.dwPlatformId && 
		osvi.dwMajorVersion > 4 )
	{
		StringCchCopy(pszOS, BUFSIZE, TEXT("Microsoft "));

		// Test for the specific product.

		if ( osvi.dwMajorVersion == 6 )
		{
			if( osvi.dwMinorVersion == 0 )
			{
				if( osvi.wProductType == VER_NT_WORKSTATION )
					StringCchCat(pszOS, BUFSIZE, TEXT("Windows Vista "));
				else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2008 " ));
			}

			if ( osvi.dwMinorVersion == 1 )
			{
				if( osvi.wProductType == VER_NT_WORKSTATION )
					StringCchCat(pszOS, BUFSIZE, TEXT("Windows 7 "));
				else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2008 R2 " ));
			}

			pGPI = (PGPI) GetProcAddress(
				GetModuleHandle(TEXT("kernel32.dll")), 
				"GetProductInfo");

			pGPI( osvi.dwMajorVersion, osvi.dwMinorVersion, 0, 0, &dwType);

			switch( dwType )
			{
			case PRODUCT_ULTIMATE:
				StringCchCat(pszOS, BUFSIZE, TEXT("Ultimate Edition" ));
				break;
			case PRODUCT_PROFESSIONAL:
				StringCchCat(pszOS, BUFSIZE, TEXT("Professional" ));
				break;
			case PRODUCT_HOME_PREMIUM:
				StringCchCat(pszOS, BUFSIZE, TEXT("Home Premium Edition" ));
				break;
			case PRODUCT_HOME_BASIC:
				StringCchCat(pszOS, BUFSIZE, TEXT("Home Basic Edition" ));
				break;
			case PRODUCT_ENTERPRISE:
				StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition" ));
				break;
			case PRODUCT_BUSINESS:
				StringCchCat(pszOS, BUFSIZE, TEXT("Business Edition" ));
				break;
			case PRODUCT_STARTER:
				StringCchCat(pszOS, BUFSIZE, TEXT("Starter Edition" ));
				break;
			case PRODUCT_CLUSTER_SERVER:
				StringCchCat(pszOS, BUFSIZE, TEXT("Cluster Server Edition" ));
				break;
			case PRODUCT_DATACENTER_SERVER:
				StringCchCat(pszOS, BUFSIZE, TEXT("Datacenter Edition" ));
				break;
			case PRODUCT_DATACENTER_SERVER_CORE:
				StringCchCat(pszOS, BUFSIZE, TEXT("Datacenter Edition (core installation)" ));
				break;
			case PRODUCT_ENTERPRISE_SERVER:
				StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition" ));
				break;
			case PRODUCT_ENTERPRISE_SERVER_CORE:
				StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition (core installation)" ));
				break;
			case PRODUCT_ENTERPRISE_SERVER_IA64:
				StringCchCat(pszOS, BUFSIZE, TEXT("Enterprise Edition for Itanium-based Systems" ));
				break;
			case PRODUCT_SMALLBUSINESS_SERVER:
				StringCchCat(pszOS, BUFSIZE, TEXT("Small Business Server" ));
				break;
			case PRODUCT_SMALLBUSINESS_SERVER_PREMIUM:
				StringCchCat(pszOS, BUFSIZE, TEXT("Small Business Server Premium Edition" ));
				break;
			case PRODUCT_STANDARD_SERVER:
				StringCchCat(pszOS, BUFSIZE, TEXT("Standard Edition" ));
				break;
			case PRODUCT_STANDARD_SERVER_CORE:
				StringCchCat(pszOS, BUFSIZE, TEXT("Standard Edition (core installation)" ));
				break;
			case PRODUCT_WEB_SERVER:
				StringCchCat(pszOS, BUFSIZE, TEXT("Web Server Edition" ));
				break;
			}
		}

		if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2 )
		{
			if( GetSystemMetrics(SM_SERVERR2) )
				StringCchCat(pszOS, BUFSIZE, TEXT( "Windows Server 2003 R2, "));
			else if ( osvi.wSuiteMask & VER_SUITE_STORAGE_SERVER )
				StringCchCat(pszOS, BUFSIZE, TEXT( "Windows Storage Server 2003"));
			else if ( osvi.wSuiteMask & VER_SUITE_WH_SERVER )
				StringCchCat(pszOS, BUFSIZE, TEXT( "Windows Home Server"));
			else if( osvi.wProductType == VER_NT_WORKSTATION &&
				si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64)
			{
				StringCchCat(pszOS, BUFSIZE, TEXT( "Windows XP Professional x64 Edition"));
			}
			else StringCchCat(pszOS, BUFSIZE, TEXT("Windows Server 2003, "));

			// Test for the server type.
			if ( osvi.wProductType != VER_NT_WORKSTATION )
			{
				if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_IA64 )
				{
					if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
						StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter Edition for Itanium-based Systems" ));
					else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
						StringCchCat(pszOS, BUFSIZE, TEXT( "Enterprise Edition for Itanium-based Systems" ));
				}

				else if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 )
				{
					if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
						StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter x64 Edition" ));
					else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
						StringCchCat(pszOS, BUFSIZE, TEXT( "Enterprise x64 Edition" ));
					else StringCchCat(pszOS, BUFSIZE, TEXT( "Standard x64 Edition" ));
				}

				else
				{
					if ( osvi.wSuiteMask & VER_SUITE_COMPUTE_SERVER )
						StringCchCat(pszOS, BUFSIZE, TEXT( "Compute Cluster Edition" ));
					else if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
						StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter Edition" ));
					else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
						StringCchCat(pszOS, BUFSIZE, TEXT( "Enterprise Edition" ));
					else if ( osvi.wSuiteMask & VER_SUITE_BLADE )
						StringCchCat(pszOS, BUFSIZE, TEXT( "Web Edition" ));
					else StringCchCat(pszOS, BUFSIZE, TEXT( "Standard Edition" ));
				}
			}
		}

		if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1 )
		{
			StringCchCat(pszOS, BUFSIZE, TEXT("Windows XP "));
			if( osvi.wSuiteMask & VER_SUITE_PERSONAL )
				StringCchCat(pszOS, BUFSIZE, TEXT( "Home Edition" ));
			else StringCchCat(pszOS, BUFSIZE, TEXT( "Professional" ));
		}

		if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0 )
		{
			StringCchCat(pszOS, BUFSIZE, TEXT("Windows 2000 "));

			if ( osvi.wProductType == VER_NT_WORKSTATION )
			{
				StringCchCat(pszOS, BUFSIZE, TEXT( "Professional" ));
			}
			else 
			{
				if( osvi.wSuiteMask & VER_SUITE_DATACENTER )
					StringCchCat(pszOS, BUFSIZE, TEXT( "Datacenter Server" ));
				else if( osvi.wSuiteMask & VER_SUITE_ENTERPRISE )
					StringCchCat(pszOS, BUFSIZE, TEXT( "Advanced Server" ));
				else StringCchCat(pszOS, BUFSIZE, TEXT( "Server" ));
			}
		}

		// Include service pack (if any) and build number.

		if( _tcslen(osvi.szCSDVersion) > 0 )
		{
			StringCchCat(pszOS, BUFSIZE, TEXT(" ") );
			StringCchCat(pszOS, BUFSIZE, osvi.szCSDVersion);
		}

		TCHAR buf[80];

		StringCchPrintf( buf, 80, TEXT(" (build %d)"), osvi.dwBuildNumber);
		StringCchCat(pszOS, BUFSIZE, buf);

		if ( osvi.dwMajorVersion >= 6 )
		{
			if ( si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64 )
				StringCchCat(pszOS, BUFSIZE, TEXT( ", 64-bit" ));
			else if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL )
				StringCchCat(pszOS, BUFSIZE, TEXT(", 32-bit"));
		}

		verOS = pszOS;

		return true; 
	}

	else
	{  
		printf( "This sample does not support this version of Windows.\n");
		return false;
	}
}


__declspec (dllexport) bool aplGetFormatedStringDateAsOleDate(CString &buf, COleDateTime &time)
{
	return time.ParseDateTime(buf)==TRUE;
}

#define MAX_DATE_BUF 1024

__declspec (dllexport) bool aplGetFormatedDateTime(CString buf, CString &res)
{
	res.Empty();
	if(buf.IsEmpty()) return true;

	COleDateTime time;
	time.SetStatus(COleDateTime::null);
	if(buf.GetLength()!=14)
		return false;
	int nYear,  nMonth,  nDay,  nHour,  nMin,  nSec;

	nYear=_atoi(LPCTSTR(buf.Left(4)));
	nMonth=_atoi(LPCTSTR(buf.Mid(4,2)));
	nDay=_atoi(LPCTSTR(buf.Mid(6,2)));
	nHour=_atoi(LPCTSTR(buf.Mid(8,2)));
	nMin=_atoi(LPCTSTR(buf.Mid(10,2)));
	nSec=_atoi(LPCTSTR(buf.Mid(12,2)));
	nSec = nSec<60?nSec:0;
	nMin = nMin<60?nMin:0;
	nHour = nHour<24? nHour:0;
	time.SetDateTime(nYear,  nMonth,  nDay,  nHour,  nMin,  nSec);
	return aplGetFormatedDateTime(time, res);
}

__declspec (dllexport) bool aplGetFormatedDateTime(COleDateTime &time, CString &res)
{
	res.Format(_T("%s %s"), time.Format(VAR_DATEVALUEONLY), time.Format(_T("%H:%M")));

	return true;
}

__declspec (dllexport) bool aplGetAsDateTime(CString buf, CString &res)
{
	res.Empty();
	if(buf.IsEmpty()) return true;
	if(buf.GetLength()!=14)
		return false;

	int nYear,  nMonth,  nDay,  nHour,  nMin,  nSec;
	nYear=_atoi(LPCTSTR(buf.Left(4)));
	nMonth=_atoi(LPCTSTR(buf.Mid(4,2)));
	nDay=_atoi(LPCTSTR(buf.Mid(6,2)));
	nHour=_atoi(LPCTSTR(buf.Mid(8,2)));
	nMin=_atoi(LPCTSTR(buf.Mid(10,2)));
	nSec=_atoi(LPCTSTR(buf.Mid(12,2)));

	res.Format(_T("%02d.%02d.%d %02d:%02d:%02d"), nDay, nMonth, nYear, nHour, nMin, nSec);

	return true;
}

__declspec (dllexport) bool aplGetFormatedDate(CString buf, CString &res)
{
	res.Empty();
	if(buf.IsEmpty())
		return true;

	COleDateTime time;
	time.SetStatus(COleDateTime::null);
	if(buf.GetLength()!=14)
		return false;
	int nYear,  nMonth,  nDay,  nHour,  nMin,  nSec;

	nYear=_atoi(LPCTSTR(buf.Left(4)));
	nMonth=_atoi(LPCTSTR(buf.Mid(4,2)));
	nDay=_atoi(LPCTSTR(buf.Mid(6,2)));
	nHour=_atoi(LPCTSTR(buf.Mid(8,2)));
	nMin=_atoi(LPCTSTR(buf.Mid(10,2)));
	nSec=_atoi(LPCTSTR(buf.Mid(12,2)));
	nSec = nSec<60?nSec:0;
	nMin = nMin<60?nMin:0;
	nHour = nHour<24? nHour:0;
	time.SetDateTime(nYear,  nMonth,  nDay,  nHour,  nMin,  nSec);

	return aplGetFormatedDate(time, res);
}

__declspec (dllexport) bool aplGetFormatedDate(COleDateTime &time, CString &res)
{
	res.Empty();
	TCHAR* res_date = new TCHAR[MAX_DATE_BUF];
	memset(res_date, 0, MAX_DATE_BUF);
	SYSTEMTIME SysTime;
	time.GetAsSystemTime(SysTime);
	int r = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &SysTime, NULL, res_date, MAX_DATE_BUF);
	res = res_date;
	delete []res_date;
	return r!=0;
}

__declspec (dllexport) bool aplGetFormatedDate(SYSTEMTIME &time, CString &res)
{
	res.Empty();
	TCHAR* res_date = new TCHAR[MAX_DATE_BUF];
	memset(res_date, 0, MAX_DATE_BUF);
	int r = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &time, NULL, res_date, MAX_DATE_BUF);
	res = res_date;
	delete []res_date;
	return r!=0;
}

__declspec (dllexport) bool aplGetFormatedTime(CString buf, CString &res)
{
	res.Empty();
	if(buf.IsEmpty())
		return true;
	TCHAR* res_date = new TCHAR[MAX_DATE_BUF];
	memset(res_date, 0, MAX_DATE_BUF);
	COleDateTime time;
	SYSTEMTIME SysTime;
	time.SetStatus(COleDateTime::null);
	if(buf.GetLength()!=14)
		return false;
	int nYear,  nMonth,  nDay,  nHour,  nMin,  nSec;

	nYear=_atoi(LPCTSTR(buf.Left(4)));
	nMonth=_atoi(LPCTSTR(buf.Mid(4,2)));
	nDay=_atoi(LPCTSTR(buf.Mid(6,2)));
	nHour=_atoi(LPCTSTR(buf.Mid(8,2)));
	nMin=_atoi(LPCTSTR(buf.Mid(10,2)));
	nSec=_atoi(LPCTSTR(buf.Mid(12,2)));
	nSec = nSec<60?nSec:0;
	nMin = nMin<60?nMin:0;
	nHour = nHour<24? nHour:0;
	time.SetDateTime(nYear,  nMonth,  nDay,  nHour,  nMin,  nSec);

	time.GetAsSystemTime(SysTime);
	int r = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_FORCE24HOURFORMAT|TIME_NOSECONDS, &SysTime, NULL, res_date, MAX_DATE_BUF);
	res = res_date;
	delete []res_date;
	return r!=0;
}

__declspec (dllexport) bool aplGetFormatedTime(COleDateTime &time, CString &res)
{
	res.Empty();
	TCHAR* res_date = new TCHAR[MAX_DATE_BUF];
	memset(res_date, 0, MAX_DATE_BUF);
	SYSTEMTIME SysTime;
	time.GetAsSystemTime(SysTime);
	int r = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_FORCE24HOURFORMAT|TIME_NOSECONDS, &SysTime, NULL, res_date, MAX_DATE_BUF);
	res = res_date;
	delete []res_date;
	return r!=0;
}

__declspec (dllexport) bool aplGetFormatedTime(SYSTEMTIME &time, CString &res)
{
	res.Empty();
	TCHAR* res_date = new TCHAR[MAX_DATE_BUF];
	memset(res_date, 0, MAX_DATE_BUF);
	int r = GetTimeFormat(LOCALE_USER_DEFAULT, TIME_FORCE24HOURFORMAT|TIME_NOSECONDS, &time, NULL, res_date, MAX_DATE_BUF);
	res = res_date;
	delete []res_date;
	return r!=0;
}


__declspec (dllexport) CString StrE2Str(const TCHAR *buf, int iPrec)
{
	return Double2Str(Str2Double(buf),iPrec);
}
__declspec (dllexport) CString Double2Str(double dVal, int iPrec)
{
	CString sBuf,ss;
	int iPos,i,pos2;
	TCHAR c = *localeconv()->decimal_point;
	sBuf.Format(_T("%0.17f"),dVal);
	sBuf.TrimRight(_T('0'));
	sBuf.TrimRight(c);
	iPos = sBuf.Find(c);
	bool bFlag = false;
	if (iPos!=-1)
	{
		i=iPrec;
		while (i--)
			ss+="0";
		iPos++;
		while(sBuf[iPos]==_T('0'))
			iPos++;
		pos2 = sBuf.Find(ss,iPos+1);
		if (pos2!=-1)
		{
			i = pos2;
			while (sBuf[i]==_T('0'))
				i--;
			if (sBuf[i]!=c)
			{
				sBuf = sBuf.Left(pos2);
				sBuf.TrimRight(_T('0'));
				sBuf.TrimRight(c);
				bFlag = true;
			}
		}
		else
			bFlag = true;
		while (bFlag)
		{
			ss.Replace(_T('0'),_T('9'));
			pos2 = sBuf.Find(ss,iPos);
			if (pos2!=-1)
			{
				i = pos2;
				while (sBuf[i]==_T('9'))
					i--;
				if (sBuf[i]==c)
					pos2 = i;
				sBuf.SetAt(pos2-1,char(sBuf[pos2-1]+1));
				sBuf = sBuf.Left(pos2);
				sBuf.TrimRight(_T('0'));
				sBuf.TrimRight(c);
			}
			else
				bFlag = false;

		}
	}
	return sBuf;
}

__declspec (dllexport) double Str2Double(const TCHAR* str)
{
	double dval;
	static TCHAR buf[1024];
	_strcpy(buf,str);
	TCHAR* ptr = buf;
	TCHAR f,t;
	switch(*localeconv()->decimal_point)
	{
	case _T('.'):
		f=_T(',');
		t=_T('.');
		break;
	case _T(','):
		f=_T('.');
		t=_T(',');
		break;
	}
	while (*ptr!=_T('\0'))
	{
		if (*ptr==f)
			*ptr = t;
		ptr++;
	}
	dval = __atof(buf);
	return dval;
}

__declspec (dllexport) void GetClientVer(CString &sVer)
{
	CString ininame, buf;
	HMODULE hModule = GetModuleHandle(NULL);
	if(hModule)
	{
		TCHAR *pBuf = new TCHAR[2048];
		GetModuleFileName(hModule, pBuf, 2048);
		ininame = pBuf;
		delete []pBuf;
		ininame = ininame.Left(ininame.ReverseFind(_T('\\'))+1);
	}
	ininame +="pss.ver";

	CaplStringFile f;
	if(f.Open(ininame,CFile::modeRead|CFile::shareDenyRead|CFile::typeText))
	{
		while (f.ReadString(buf))
		{
			int i=buf.Find(_T("pssver="));
			if(i>=0)
			{
				sVer=buf.Right(buf.GetLength()-7);
				break;
			}
		}
		f.Close();
	}
}

__declspec (dllexport) COLORREF aplFusionColors(COLORREF color1, COLORREF color2, double k1, double k2)
{
	BYTE r, g, b;
	BYTE r1, g1, b1;
	BYTE r2, g2, b2;

	r1 = GetRValue(color1);
	g1 = GetGValue(color1);
	b1 = GetBValue(color1);

	r2 = GetRValue(color2);
	g2 = GetGValue(color2);
	b2 = GetBValue(color2);

	r = (int)(r1*k1+r2*k2); //if(r>255) r=255; переменная типа BYTE не может быть больше 255 :)
	g = (int)(g1*k1+g2*k2); //if(g>255) g=255;
	b = (int)(b1*k1+b2*k2); //if(b>255) b=255;

	return RGB(r, g, b);
}

__declspec (dllexport) bool aplGetGradientBitmap(CDC *pDC, CRect rect, COLORREF color1, COLORREF color2, CBitmap *bmp, bool bUseShadow)
{
	if(bmp==NULL) return false;
	if(bmp->GetSafeHandle()!=NULL)
		bmp->DeleteObject();

	int i, j;
	int width(rect.Width()), height(rect.Height());
	COLORREF color;
	COLORREF	*pColors = new COLORREF[width*height];
	memset(pColors, 0, sizeof(COLORREF)*width*height);

	BYTE r1, r2, g1, g2, b1, b2;

	r1 = GetRValue(color1);
	g1 = GetGValue(color1);
	b1 = GetBValue(color1);

	r2 = GetRValue(color2);
	g2 = GetGValue(color2);
	b2 = GetBValue(color2);

	if(bUseShadow)
	{
		int iStart = height/5;
		int h = height-iStart;

		for(i=iStart; i<height; i++)
		{
			color = RGB(b1+(((b2-b1)*(i-iStart))/h), g1+(((g2-g1)*(i-iStart))/h), r1+(((r2-r1)*(i-iStart))/h));
			for(j=0; j<width; ++j)
				pColors[i*width+j] = color;
		}

		r2 = (BYTE)(r1*0.9);
		g2 = (BYTE)(g1*0.9);
		b2 = (BYTE)(b1*0.9);

		h = iStart;
		for(i=iStart; i>-1; i--)
		{
			color = RGB(b1+(((b2-b1)*i)/h), g1+(((g2-g1)*i)/h), r1+(((r2-r1)*i)/h));
			for(j=0; j<width; ++j)
				pColors[(iStart-i)*width+j] = color;
		}
	}
	else
	{
		int h = height;
		for(i=0; i<height; i++)
		{
			color = RGB(b1+(((b2-b1)*i)/h), g1+(((g2-g1)*i)/h), r1+(((r2-r1)*i)/h));
			for(j=0; j<width; ++j)
				pColors[i*width+j] = color;
		}
	}

	BITMAPINFO bmpInfo = {sizeof(BITMAPINFOHEADER), width, height, 1, 32, BI_RGB, 0, 0, 0, 0, 0};
	HBITMAP hBMP(::CreateDIBitmap(pDC->GetSafeHdc(), &bmpInfo.bmiHeader, CBM_INIT, pColors, &bmpInfo, DIB_RGB_COLORS));
	bmp->Attach(hBMP);
	delete []pColors;

	return true;
}

__declspec (dllexport) bool aplGetAsHM(double dVal, CString &sVal)
{
	int hour = (int)dVal;
	int minutes(0);
	if(dVal>0)
		minutes = (int)((dVal - (double)hour)*60+0.5);
	else if(dVal<0)
		minutes = (int)((dVal - (double)hour)*60-0.5);
	if(minutes!=0)
		sVal.Format(_T("%d:%02d"), hour, minutes>0?minutes:-minutes);
	else
		sVal.Format(_T("%d"), hour);
	return true;
}
/************************************************************************/
__declspec (dllexport) bool aplGetAsHM(double dVal, double dMinVal, double dMaxVal, CString &sVal)
{
	CString buf;
	int hour = (int)dVal;
	int minutes = hour>0?((int)((dVal - (double)hour)*60+0.5)):((int)((dVal - (double)hour)*60-0.5));
	if(minutes!=0)
		sVal.Format(_T("%d:%02d"), hour, minutes>0?minutes:-minutes);
	else
		sVal.Format(_T("%d"), hour);
	if(dMaxVal!=0 && dMaxVal==dMinVal)
	{
		hour = (int)dMaxVal;
		minutes = hour>0?((int)((dVal - (double)hour)*60+0.5)):((int)((dVal - (double)hour)*60-0.5));
		if(minutes>0)
			buf.Format(_T(" +/-%d:%02d"), hour, minutes);
		else
			buf.Format(_T(" +/-%d"), hour);
		sVal+=buf;
	}
	else
	{
		if(dMaxVal!=0)
		{
			hour = (int)dMaxVal;
			minutes = hour>0?((int)((dMaxVal - (double)hour)*60+0.5)):((int)((dMaxVal - (double)hour)*60-0.5));
			if(minutes>0)
				buf.Format(_T(" +%d:%02d"), hour, minutes);
			else
				buf.Format(_T(" +%d"), hour);
			sVal+=buf;
		}
		if(dMinVal!=0)
		{
			hour = (int)dMinVal;
			minutes = hour>0?((int)((dMinVal - (double)hour)*60+0.5)):((int)((dMinVal - (double)hour)*60-0.5));
			if(minutes!=0)
				buf.Format(_T("%s-%d:%02d"), dMaxVal!=0?_T("/"):_T(" "), hour, minutes>0?minutes:-minutes);
			else
				buf.Format(_T("%s-%d"), dMaxVal!=0?_T("/"):_T(" "), hour);
			sVal+=buf;
		}
	}
	return true;
}

__declspec (dllexport) bool aplGetAsDouble(LPCTSTR sVal, double &dVal, int *Hour, int *Minutes)
{
	CString m, h, str;
	int i;
	int M = 0, H = 0;
	str = sVal;
	str.Trim();
	str.Remove(_T(' '));
	int ind = str.Find(_T(":"));
	ind = ind>-1?ind:str.Find(_T("/"));
	ind = ind>-1?ind:str.Find(_T("\\"));
	ind = ind>-1?ind:str.Find(_T("="));
	ind = ind>-1?ind:str.Find(_T("*"));
	ind = ind>-1?ind:str.Find(_T("`"));
	CString t;
	if(ind>0)
	{
		t = str.Left(ind);
		for(i=0; i<t.GetLength(); i++)
			if(!_isdigit(t[i])) return false;
		H = _atoi(t);
		str.TrimLeft(t);
		str.TrimLeft(_T(":"));
		str.TrimLeft(_T("/"));
		str.TrimLeft(_T("\\"));
		str.TrimLeft(_T("="));
		str.TrimLeft(_T("*"));
		str.TrimLeft(_T("`"));
		if(str.GetLength()!=2) return false;
		for(i=0; i<2; i++)
		{
			if(!_isdigit(str[i])) return false;
		}
		M = _atoi(str);
		if(M>59) return false;
		dVal = (double)H + ((double)M)/60;
		if(Hour)
			*Hour = H;
		if(Minutes)
			*Minutes = M;
		return true;
	}
	else 
	{
		if(!IsReal(str)) return false;

		dVal = __atof(str);
		if(Hour)
			*Hour = _atoi(str);
		if(Minutes)
			*Minutes = 0;
		return true;
	}
}
/************************************************************************/
__declspec (dllexport) bool aplGetAsDouble(LPCTSTR sVal, double &dVal, double &dMinVal, double &dMaxVal)
{
	dVal = 0;
	dMinVal=0;
	dMaxVal=0;
	int PlusFind, MinusFind, ValInd;
	CString buf, val;
	bool bUseOne = false;
	val = sVal;
	val.Trim();
	val.Remove(_T(' '));
	if(val.IsEmpty()) return true;
	PlusFind = val.Find(_T("+"), 1);
	MinusFind = val.Find(_T("-"), 1); //ищем 
	ValInd = PlusFind>MinusFind && MinusFind>0 ? MinusFind : PlusFind;
	if(ValInd>-1)
	{
		buf = val.Left(ValInd);
		if(buf.IsEmpty())
			return true;
		if(!aplGetAsDouble(buf, dVal)) 
			return false;
	}
	else
	{
		if(!aplGetAsDouble(val, dVal)) 
			return false;
	}
	if(PlusFind>-1 && MinusFind<0)
	{
		buf = val.Mid(PlusFind+1, val.GetLength()-PlusFind-1);
		if(buf.IsEmpty())
			return false;
		if(!aplGetAsDouble(buf, dMaxVal)) 
			return false;
	}
	if(MinusFind>-1 && PlusFind<0)
	{
		buf = val.Mid(MinusFind+1, val.GetLength()-MinusFind-1);
		if(buf.IsEmpty())
			return false;
		if(!aplGetAsDouble(buf, dMinVal)) 
			return false;
	}
	if(PlusFind>-1 && PlusFind<MinusFind)
	{
		//Необходимо определить верхнее и нижнее отклонение
		buf = val.Mid(PlusFind+1, MinusFind-PlusFind-1);//Верхнее
		if(!aplGetAsDouble(buf, dMaxVal)) 
			return false;
		else if(buf.IsEmpty())
			bUseOne = true;
		buf = val.Mid(MinusFind+1, val.GetLength()-MinusFind-1);//Нижнее
		if(!aplGetAsDouble(buf, dMinVal))
			return false;
		else if(buf.IsEmpty())
			return false;
		if(bUseOne)
			dMaxVal = dMinVal;
	}
	if(MinusFind>-1 && MinusFind<PlusFind)
	{
		//Необходимо определить верхнее и нижнее отклонение
		buf = val.Mid(MinusFind+1, PlusFind-MinusFind-1);//Нижнее
		if(!aplGetAsDouble(buf, dMinVal)) 
			return false;
		else if(buf.IsEmpty())
			bUseOne = true;
		buf = val.Mid(PlusFind+1, val.GetLength()-PlusFind-1);//верхнее
		if(!aplGetAsDouble(buf, dMaxVal)) 
			return false;
		else if(buf.IsEmpty())
			return false;
		if(bUseOne)
			dMinVal = dMaxVal;
	}
	return true;
}

void UpdatePopupMenu(CCmdTarget* pTarget, CMenu *pPopup)
{
	UINT i;
	for(i=0; i<pPopup->GetMenuItemCount(); ++i)
	{
		UINT menuId = pPopup->GetMenuItemID(i);
		if(menuId!=0)
		{
			CCmdUI cmdUI;
			cmdUI.m_nID = menuId;
			cmdUI.m_pMenu = pPopup;
			cmdUI.m_nIndex = i;
			cmdUI.m_nIndexMax = pPopup->GetMenuItemCount();
			cmdUI.m_pSubMenu = NULL;
			cmdUI.DoUpdate(pTarget, TRUE);
		}

		CMenu *pSubMenu = pPopup->GetSubMenu(i);
		if(pSubMenu)
			UpdatePopupMenu(pTarget, pSubMenu);
	}
}

bool aplCopyFile(const CString& sSourceFile, const CString& sDestPath, bool bDeleteSourceFile /* = false */)
{
	if (sSourceFile.IsEmpty() || sDestPath.IsEmpty())
		return false;

	CString sFileName;
	int iFind = sSourceFile.ReverseFind(_T('\\'));
	if (iFind < 0)
		return false;	// нужен путь, чтобы найти файл
	sFileName = sSourceFile.Right(sSourceFile.GetLength()-iFind-1);
	if (sFileName.IsEmpty())
		return false;

	CString sDestFile = sDestPath;
	sDestFile.TrimRight(_T('\\'));
	sDestFile += _T("\\");
	sDestFile += sFileName;

	CFile sourceFile;
	CFile destFile;
	if (!sourceFile.Open((LPCTSTR)sSourceFile, CFile::modeRead | CFile::shareDenyWrite))
		return false;

	if (!destFile.Open((LPCTSTR)sDestFile, CFile::modeWrite | CFile::shareExclusive | CFile::modeCreate))
	{
		sourceFile.Close();
		return false;
	}

	BYTE buffer[4096];
	DWORD dwRead;
	do
	{
		dwRead = sourceFile.Read(buffer, 4096);
		destFile.Write(buffer, dwRead);
	} while (dwRead > 0);

	destFile.Close();
	sourceFile.Close();

	if (bDeleteSourceFile)
	{
		DWORD attrs = ::GetFileAttributes(sSourceFile);
		if (attrs&FILE_ATTRIBUTE_READONLY)
		{
			attrs &= ~FILE_ATTRIBUTE_READONLY;
			::SetFileAttributes(sSourceFile, attrs);
		}
		::DeleteFile(sSourceFile);
	}

	return true;
}