1126 lines
24 KiB
C++
1126 lines
24 KiB
C++
#include "pch.h"
|
|
#include <windows.h>
|
|
#include <string>
|
|
#include <algorithm>
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <chrono>
|
|
#include <ctime>
|
|
#include <iomanip>
|
|
#include <sstream>
|
|
#include <random> // C++11의 고품질 랜덤 라이브러리
|
|
#include <chrono> // 시간 기반의 시드값 생성을 위해 사용
|
|
#include <tlhelp32.h> // Tool-Help 라이브러리
|
|
#pragma warning(disable:4996)
|
|
|
|
//
|
|
// convert_ansi_to_unicode_string.
|
|
//
|
|
|
|
DWORD convert_ansi_to_unicode_string(
|
|
__out std::wstring& unicode,
|
|
__in const char* ansi,
|
|
__in const size_t ansi_size
|
|
) {
|
|
|
|
DWORD error = 0;
|
|
|
|
do {
|
|
|
|
if ((NULL == ansi) || (0 == ansi_size)) {
|
|
error = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
unicode.clear();
|
|
|
|
//
|
|
// getting required cch.
|
|
//
|
|
|
|
int required_cch = ::MultiByteToWideChar(
|
|
CP_ACP,
|
|
0,
|
|
ansi, static_cast<int>(ansi_size),
|
|
NULL, 0
|
|
);
|
|
|
|
if (0 == required_cch) {
|
|
error = ::GetLastError();
|
|
break;
|
|
}
|
|
|
|
unicode.resize(required_cch);
|
|
|
|
//
|
|
// convert.
|
|
//
|
|
|
|
if (0 == ::MultiByteToWideChar(
|
|
CP_ACP,
|
|
0,
|
|
ansi, static_cast<int>(ansi_size),
|
|
const_cast<wchar_t*>(unicode.c_str()), static_cast<int>(unicode.size())
|
|
)) {
|
|
error = ::GetLastError();
|
|
break;
|
|
}
|
|
|
|
} while (false);
|
|
|
|
return error;
|
|
}
|
|
|
|
//
|
|
// convert_unicode_to_ansi_string.
|
|
//
|
|
|
|
DWORD convert_unicode_to_ansi_string(
|
|
__out std::string& ansi,
|
|
__in const wchar_t* unicode,
|
|
__in const size_t unicode_size
|
|
) {
|
|
|
|
DWORD error = 0;
|
|
|
|
do {
|
|
|
|
if ((NULL == unicode) || (0 == unicode_size)) {
|
|
error = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
ansi.clear();
|
|
|
|
//
|
|
// getting required cch.
|
|
//
|
|
|
|
int required_cch = ::WideCharToMultiByte(
|
|
CP_ACP,
|
|
0,
|
|
unicode, static_cast<int>(unicode_size),
|
|
NULL, 0,
|
|
NULL, NULL
|
|
);
|
|
|
|
if (0 == required_cch) {
|
|
error = ::GetLastError();
|
|
break;
|
|
}
|
|
|
|
//
|
|
// allocate.
|
|
//
|
|
|
|
ansi.resize(required_cch);
|
|
|
|
//
|
|
// convert.
|
|
//
|
|
|
|
if (0 == ::WideCharToMultiByte(
|
|
CP_ACP,
|
|
0,
|
|
unicode, static_cast<int>(unicode_size),
|
|
const_cast<char*>(ansi.c_str()), static_cast<int>(ansi.size()),
|
|
NULL, NULL
|
|
)) {
|
|
error = ::GetLastError();
|
|
break;
|
|
}
|
|
|
|
} while (false);
|
|
|
|
return error;
|
|
}
|
|
|
|
//
|
|
// convert_unicode_to_utf8_string
|
|
//
|
|
|
|
DWORD convert_unicode_to_utf8_string(
|
|
__out std::string& utf8,
|
|
__in const wchar_t* unicode,
|
|
__in const size_t unicode_size
|
|
) {
|
|
|
|
DWORD error = 0;
|
|
|
|
do {
|
|
|
|
if ((NULL == unicode) || (0 == unicode_size)) {
|
|
error = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
utf8.clear();
|
|
|
|
//
|
|
// getting required cch.
|
|
//
|
|
|
|
int required_cch = ::WideCharToMultiByte(
|
|
CP_UTF8,
|
|
WC_ERR_INVALID_CHARS,
|
|
unicode, static_cast<int>(unicode_size),
|
|
NULL, 0,
|
|
NULL, NULL
|
|
);
|
|
|
|
if (0 == required_cch) {
|
|
error = ::GetLastError();
|
|
break;
|
|
}
|
|
|
|
//
|
|
// allocate.
|
|
//
|
|
|
|
utf8.resize(required_cch);
|
|
|
|
//
|
|
// convert.
|
|
//
|
|
|
|
if (0 == ::WideCharToMultiByte(
|
|
CP_UTF8,
|
|
WC_ERR_INVALID_CHARS,
|
|
unicode, static_cast<int>(unicode_size),
|
|
const_cast<char*>(utf8.c_str()), static_cast<int>(utf8.size()),
|
|
NULL, NULL
|
|
)) {
|
|
error = ::GetLastError();
|
|
break;
|
|
}
|
|
|
|
} while (false);
|
|
|
|
return error;
|
|
}
|
|
|
|
//
|
|
// convert_utf8_to_unicode_string
|
|
//
|
|
|
|
DWORD convert_utf8_to_unicode_string(
|
|
__out std::wstring& unicode,
|
|
__in const char* utf8,
|
|
__in const size_t utf8_size
|
|
) {
|
|
|
|
DWORD error = 0;
|
|
|
|
do {
|
|
|
|
if ((NULL == utf8) || (0 == utf8_size)) {
|
|
error = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
unicode.clear();
|
|
|
|
//
|
|
// getting required cch.
|
|
//
|
|
|
|
int required_cch = ::MultiByteToWideChar(
|
|
CP_UTF8,
|
|
MB_ERR_INVALID_CHARS,
|
|
utf8, static_cast<int>(utf8_size),
|
|
NULL, 0
|
|
);
|
|
if (0 == required_cch) {
|
|
error = ::GetLastError();
|
|
break;
|
|
}
|
|
|
|
//
|
|
// allocate.
|
|
//
|
|
|
|
unicode.resize(required_cch);
|
|
|
|
//
|
|
// convert.
|
|
//
|
|
|
|
if (0 == ::MultiByteToWideChar(
|
|
CP_UTF8,
|
|
MB_ERR_INVALID_CHARS,
|
|
utf8, static_cast<int>(utf8_size),
|
|
const_cast<wchar_t*>(unicode.c_str()), static_cast<int>(unicode.size())
|
|
)) {
|
|
error = ::GetLastError();
|
|
break;
|
|
}
|
|
|
|
} while (false);
|
|
|
|
return error;
|
|
}
|
|
|
|
|
|
DWORD convert_utf8_to_unicode_pointer(
|
|
__out wchar_t ** unicode,
|
|
__in const char* utf8,
|
|
__in const size_t utf8_size
|
|
)
|
|
{
|
|
DWORD error = 0;
|
|
WCHAR * buff = NULL;
|
|
do {
|
|
|
|
if ((NULL == utf8) || (0 == utf8_size)) {
|
|
error = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// getting required cch.
|
|
//
|
|
|
|
int required_cch = ::MultiByteToWideChar(
|
|
CP_UTF8,
|
|
MB_ERR_INVALID_CHARS,
|
|
utf8, static_cast<int>(utf8_size),
|
|
NULL, 0
|
|
);
|
|
if (0 == required_cch) {
|
|
error = ::GetLastError();
|
|
break;
|
|
}
|
|
|
|
//
|
|
// allocate.
|
|
//
|
|
|
|
buff = (wchar_t *)malloc(required_cch * sizeof(wchar_t) + sizeof(wchar_t));
|
|
memset(buff, 0, required_cch * sizeof(wchar_t) + sizeof(wchar_t));
|
|
|
|
//
|
|
// convert.
|
|
//
|
|
|
|
if (0 == ::MultiByteToWideChar(
|
|
CP_UTF8,
|
|
MB_ERR_INVALID_CHARS,
|
|
utf8, static_cast<int>(utf8_size),
|
|
const_cast<wchar_t*>(buff), static_cast<int>(required_cch)
|
|
)) {
|
|
error = ::GetLastError();
|
|
break;
|
|
}
|
|
|
|
*unicode = buff;
|
|
|
|
} while (false);
|
|
|
|
return error;
|
|
}
|
|
|
|
DWORD convert_utf8_to_ansi_pointer(string &utf8_to_ansi)
|
|
{
|
|
DWORD error;
|
|
wstring uni;
|
|
string ansi;
|
|
|
|
error = convert_utf8_to_unicode_string(uni, utf8_to_ansi.c_str(), utf8_to_ansi.length());
|
|
if (error)
|
|
return error;
|
|
|
|
utf8_to_ansi = "";
|
|
|
|
error = convert_unicode_to_ansi_string(ansi, uni.c_str(), uni.length());
|
|
if (error)
|
|
return error;
|
|
|
|
utf8_to_ansi = ansi;
|
|
|
|
return error;
|
|
}
|
|
|
|
DWORD convert_ansi_to_utf8_pointer(string& ansi_to_utf8)
|
|
{
|
|
wstring uni;
|
|
string ansi;
|
|
|
|
DWORD error = convert_ansi_to_unicode_string(uni, ansi_to_utf8.c_str(), ansi_to_utf8.length());
|
|
if (error)
|
|
return error;
|
|
|
|
error = convert_unicode_to_utf8_string(ansi_to_utf8, uni.c_str(), uni.length());
|
|
if (error)
|
|
return error;
|
|
|
|
return error;
|
|
}
|
|
|
|
|
|
DWORD GetTime()
|
|
{
|
|
time_t local_now;
|
|
time(&local_now);
|
|
return (DWORD)local_now;
|
|
}
|
|
|
|
|
|
BOOL UtilRunProcessNoWait(const wchar_t* path, bool wait)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
|
|
WCHAR szCommandCode[MAX_PATH] = { 0, };
|
|
|
|
StringCbPrintfW(szCommandCode, sizeof(szCommandCode), L"%s", path);
|
|
|
|
BSONE_INFOW(L"(%s)", szCommandCode);
|
|
|
|
wchar_t workingDir[MAX_PATH];
|
|
wcscpy_s(workingDir, MAX_PATH, szCommandCode);
|
|
|
|
// 3. 전체 경로에서 파일 이름(MyCSharpApp.exe)을 제거하여 디렉터리 경로만 남김
|
|
// 이 작업의 결과로 workingDir에는 "C:\MyCSharpApp"만 남게 됩니다.
|
|
PathRemoveFileSpecW(workingDir);
|
|
|
|
STARTUPINFOW si = {0, };
|
|
PROCESS_INFORMATION pi = { 0, };
|
|
|
|
si.cb = sizeof(si);
|
|
|
|
BOOL bExecuteRet = CreateProcessW(NULL, szCommandCode, NULL, NULL, FALSE, 0, NULL, workingDir, &si, &pi);
|
|
|
|
if (!bExecuteRet)
|
|
{
|
|
BSONE_INFOW(L"CreateProcess ErrorCode(%d)", GetLastError());
|
|
return FALSE;
|
|
}
|
|
|
|
if (wait == true)
|
|
{
|
|
WaitForSingleObject(pi.hProcess, INFINITE);
|
|
BSONE_INFOW(L"WaitForSingleObject--=");
|
|
}
|
|
|
|
CloseHandle(pi.hProcess);
|
|
CloseHandle(pi.hThread);
|
|
|
|
return bExecuteRet;
|
|
}
|
|
|
|
/**
|
|
* @brief 지정된 커맨드 라인을 실행하고, 해당 프로세스가 종료될 때까지 대기합니다.
|
|
* @param hParentWnd 부모 윈도우 핸들. 비활성화/활성화 처리를 위해 필요합니다.
|
|
* @param szCommandLine 실행할 프로그램의 커맨드 라인입니다.
|
|
* @return 자식 프로세스의 종료 코드를 반환합니다. 프로세스 생성 실패 시 -1을 반환합니다.
|
|
*/
|
|
DWORD UtilCreateProcessAsModal(LPCWSTR szCommandLine)
|
|
{
|
|
HWND hParentWnd = GetActiveWindow();
|
|
// 1. 부모 윈도우 비활성화
|
|
EnableWindow(hParentWnd, FALSE);
|
|
|
|
STARTUPINFOW si = { sizeof(si) };
|
|
PROCESS_INFORMATION pi;
|
|
|
|
// 2. 자식 프로세스 실행
|
|
BOOL bSuccess = CreateProcess(
|
|
NULL, (LPWSTR)szCommandLine, NULL, NULL, FALSE,
|
|
0, NULL, NULL, &si, &pi
|
|
);
|
|
|
|
if (!bSuccess) {
|
|
//MessageBox(hParentWnd, TEXT("프로세스 생성에 실패했습니다."), TEXT("오류"), MB_OK);
|
|
EnableWindow(hParentWnd, TRUE);
|
|
return -1; // 실패 코드
|
|
}
|
|
|
|
// 3. 자식 프로세스가 끝날 때까지 대기
|
|
WaitForSingleObject(pi.hProcess, INFINITE);
|
|
|
|
// 4. 자식 프로세스의 종료 코드 가져오기
|
|
DWORD dwExitCode = 0;
|
|
GetExitCodeProcess(pi.hProcess, &dwExitCode);
|
|
|
|
// 5. 핸들 정리
|
|
CloseHandle(pi.hProcess);
|
|
CloseHandle(pi.hThread);
|
|
|
|
// 6. 부모 윈도우 다시 활성화
|
|
EnableWindow(hParentWnd, TRUE);
|
|
SetForegroundWindow(hParentWnd);
|
|
|
|
|
|
return dwExitCode;
|
|
}
|
|
|
|
DWORD
|
|
GetParentID(DWORD p_ID)
|
|
{
|
|
PROCESSENTRY32 pEntry;
|
|
BOOL bRes = FALSE;
|
|
HANDLE hSnapShot = NULL;
|
|
HANDLE hProcess = NULL;
|
|
DWORD ret = 0;
|
|
|
|
hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);
|
|
pEntry.dwSize = sizeof(pEntry);
|
|
Process32First(hSnapShot, &pEntry);
|
|
|
|
while (1)
|
|
{
|
|
bRes = Process32Next(hSnapShot, &pEntry);
|
|
if (!bRes) break;
|
|
|
|
if (pEntry.th32ProcessID == p_ID)
|
|
{
|
|
ret = pEntry.th32ParentProcessID;
|
|
break;
|
|
}
|
|
}
|
|
CloseHandle(hSnapShot);
|
|
|
|
return ret;
|
|
}
|
|
|
|
BOOL
|
|
IsWinVistaOSAbove()
|
|
{
|
|
OSVERSIONINFO osvi;
|
|
|
|
memset(&osvi, 0x00, sizeof(OSVERSIONINFO));
|
|
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
GetVersionEx(&osvi);
|
|
|
|
if (osvi.dwMajorVersion >= 6) return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
UtilExistRegKey(HKEY root, const wchar_t* key)
|
|
{
|
|
HKEY hKey;
|
|
if (RegOpenKey(root, key, &hKey) != ERROR_SUCCESS)
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
wstring
|
|
UtilGetRegValue(HKEY root, const wchar_t * key, const wchar_t* name)
|
|
{
|
|
HKEY hKey;
|
|
wchar_t tmp_buffer[1024];
|
|
|
|
memset(tmp_buffer, 0, 1024);
|
|
|
|
DWORD tmp_size = 1024;
|
|
DWORD type;
|
|
|
|
RegOpenKey(root, key, &hKey);
|
|
RegQueryValueEx(hKey, name, 0, &type, (BYTE*)tmp_buffer, &tmp_size);
|
|
RegCloseKey(hKey);
|
|
|
|
return tmp_buffer;
|
|
}
|
|
|
|
BOOL
|
|
IsWin8OSAbove()
|
|
{
|
|
OSVERSIONINFO osvi;
|
|
|
|
memset(&osvi, 0x00, sizeof(OSVERSIONINFO));
|
|
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
GetVersionEx(&osvi);
|
|
|
|
// Windows 10
|
|
if (osvi.dwMajorVersion > 6) return TRUE;
|
|
|
|
// Windows 8 (6.2) , Windows 7 (6.1)
|
|
if ((osvi.dwMajorVersion == 6) && (osvi.dwMinorVersion >= 2)) return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
typedef BOOL(__stdcall* LPFN_ISWOW64PROCESS) (HANDLE hProcess, PBOOL Wow64Process);
|
|
|
|
BOOL IsWow64()
|
|
{
|
|
//MOD5198
|
|
BOOL bIsWow64 = FALSE;
|
|
|
|
HMODULE hKernel = GetModuleHandle(_T("kernel32"));
|
|
if (hKernel)
|
|
{
|
|
LPFN_ISWOW64PROCESS fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(hKernel, "IsWow64Process");
|
|
|
|
if (NULL != fnIsWow64Process)
|
|
{
|
|
if (!fnIsWow64Process(GetCurrentProcess(), &bIsWow64))
|
|
{
|
|
// handle error
|
|
#ifdef MAXUP_DEBUG
|
|
DbgPrint("[KDFINJ] IsWow64Process Error: %u", GetLastError());
|
|
#endif
|
|
}
|
|
}
|
|
|
|
fnIsWow64Process = NULL;
|
|
FreeLibrary(hKernel);
|
|
hKernel = NULL;
|
|
}
|
|
|
|
return bIsWow64;
|
|
}
|
|
|
|
std::wstring UtilGetUserWindowID()
|
|
{
|
|
std::wstring str;
|
|
wchar_t name[MAX_PATH] = { 0, };
|
|
|
|
DWORD size = ARRAYSIZE(name);
|
|
|
|
GetUserNameW(name, &size);
|
|
str = name;
|
|
|
|
return str;
|
|
}
|
|
|
|
|
|
std::wstring UtilGetIP()
|
|
{
|
|
char chName[255] = { 0, };
|
|
//CString sAddress;
|
|
PHOSTENT pHostEntry;
|
|
IN_ADDR inAddr;
|
|
|
|
if (gethostname(chName, 255) != 0)
|
|
{
|
|
return L"";
|
|
}
|
|
else
|
|
{
|
|
if ((pHostEntry = gethostbyname(chName)) == NULL)
|
|
{
|
|
return L"";
|
|
}
|
|
else
|
|
{
|
|
memcpy(&inAddr, pHostEntry->h_addr, 4);
|
|
string addr = inet_ntoa(inAddr);
|
|
wstring waddr;
|
|
convert_ansi_to_unicode_string(waddr, addr.c_str(), addr.length());
|
|
return waddr;
|
|
}
|
|
}
|
|
|
|
return L"";
|
|
}
|
|
|
|
BOOL UtilGetIPMac(wstring& strIP, wstring& strMac)
|
|
{
|
|
PHOSTENT hostInfo = NULL;
|
|
char szHost[100] = { 0, };
|
|
|
|
int iResult = 0;
|
|
WSADATA wsaData = { 0, };
|
|
|
|
ULONG pulMac[2] = { 0, };
|
|
ULONG dwdstip = 0;
|
|
IPAddr udstaddr = { 0, };
|
|
|
|
ULONG ulLen = 6;
|
|
DWORD dwRetSARP = 0;
|
|
BYTE gwmac[6] = { 0, };
|
|
WCHAR macAddress[MAX_PATH] = { 0, };
|
|
wchar_t wszPCName[MAX_PATH] = { 0, };
|
|
DWORD dwBufferSize = MAX_PATH;
|
|
string pcname = "";
|
|
|
|
|
|
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
|
|
if (iResult != 0)
|
|
{
|
|
//BSONE_INFOA("WSAStartup Error(%d)", WSAGetLastError());
|
|
return FALSE;
|
|
}
|
|
|
|
GetComputerNameW(wszPCName, &dwBufferSize);
|
|
|
|
convert_unicode_to_ansi_string(pcname, wszPCName, wcslen(wszPCName));
|
|
//BSONE_INFOA("szPCName[%s]", pcname.c_str());
|
|
|
|
if ((hostInfo = gethostbyname(pcname.c_str())) != NULL)
|
|
{
|
|
if (*hostInfo->h_addr_list != NULL)
|
|
{
|
|
StringCbPrintfA(szHost, sizeof(szHost), "%s", inet_ntoa(*(struct in_addr*)*hostInfo->h_addr_list));
|
|
|
|
convert_ansi_to_unicode_string(strIP, szHost, strlen(szHost));
|
|
//strIP = CA2T(szHost);
|
|
|
|
//K_DEBUG(_T("GetLocalIPMac, szHost[%s]"), strIP);
|
|
//BSONE_INFOA("ip : ", strIP.c_str());
|
|
|
|
dwdstip = inet_addr(szHost);
|
|
udstaddr = dwdstip;
|
|
|
|
if (dwdstip != INADDR_NONE)
|
|
{
|
|
memset(pulMac, 0xff, sizeof(pulMac));
|
|
|
|
if ((dwRetSARP = SendARP(udstaddr, 0, pulMac, &ulLen)) == NO_ERROR)
|
|
{
|
|
memcpy(gwmac, pulMac, sizeof(gwmac)); //ULONG(8byte) 6byte만큼만 write
|
|
|
|
StringCbPrintfW(macAddress, ARRAYSIZE(macAddress), L"%02X%02X%02X%02X%02X%02X", gwmac[0], gwmac[1], gwmac[2], gwmac[3], gwmac[4], gwmac[5]);
|
|
strMac = macAddress;
|
|
|
|
//K_DEBUG(_T("GetLocalIPMac, strGWMac[%s]"), strMac.GetBuffer(0));
|
|
|
|
WSACleanup();
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
WSACleanup();
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
#include <Nb30.h>
|
|
typedef struct _ASTAT_
|
|
{
|
|
ADAPTER_STATUS adapt;
|
|
NAME_BUFFER NameBuff[30];
|
|
} ASTAT, * PASTAT;
|
|
|
|
|
|
std::wstring UtilGetMac()
|
|
{
|
|
std::wstring macaddr = L"";
|
|
NCB Ncb;
|
|
ASTAT Adapter;
|
|
UCHAR uRetCode;
|
|
LANA_ENUM lenum;
|
|
int i;
|
|
|
|
memset(&Ncb, 0, sizeof(Ncb));
|
|
Ncb.ncb_command = NCBENUM;
|
|
Ncb.ncb_buffer = (UCHAR*)&lenum;
|
|
Ncb.ncb_length = sizeof(lenum);
|
|
uRetCode = Netbios(&Ncb);
|
|
|
|
for (i = 0; i < lenum.length; i++)
|
|
{
|
|
memset(&Ncb, 0, sizeof(Ncb));
|
|
Ncb.ncb_command = NCBRESET;
|
|
Ncb.ncb_lana_num = lenum.lana[i];
|
|
uRetCode = Netbios(&Ncb);
|
|
memset(&Ncb, 0, sizeof(Ncb));
|
|
Ncb.ncb_command = NCBASTAT;
|
|
Ncb.ncb_lana_num = lenum.lana[i];
|
|
strcpy((char*)Ncb.ncb_callname, "* ");
|
|
Ncb.ncb_buffer = (unsigned char*)&Adapter;
|
|
Ncb.ncb_length = sizeof(Adapter);
|
|
uRetCode = Netbios(&Ncb);
|
|
|
|
if (uRetCode == 0)
|
|
{
|
|
wchar_t tmp[255] = { 0, };
|
|
_snwprintf(tmp,
|
|
sizeof(tmp),
|
|
L"%02x%02x%02x%02x%02x%02x",
|
|
Adapter.adapt.adapter_address[0],
|
|
Adapter.adapt.adapter_address[1],
|
|
Adapter.adapt.adapter_address[2],
|
|
Adapter.adapt.adapter_address[3],
|
|
Adapter.adapt.adapter_address[4],
|
|
Adapter.adapt.adapter_address[5]
|
|
);
|
|
macaddr = tmp;
|
|
}
|
|
}
|
|
|
|
return macaddr;
|
|
}
|
|
|
|
// CString -> std::wstring 멤버로 변경 필요
|
|
// 예시: std::wstring dmPrinterName;
|
|
// 아래 함수들에서 CString 관련 부분을 std::wstring으로 변경
|
|
|
|
// 문자열 대소문자 변환
|
|
std::wstring ToUpper(const std::wstring& str) {
|
|
std::wstring result = str;
|
|
std::transform(result.begin(), result.end(), result.begin(), ::towupper);
|
|
return result;
|
|
}
|
|
|
|
std::wstring ToLower(const std::wstring& str) {
|
|
std::wstring result = str;
|
|
std::transform(result.begin(), result.end(), result.begin(), ::towlower);
|
|
return result;
|
|
}
|
|
|
|
std::string ToUpperA(const std::string& str) {
|
|
std::string result = str;
|
|
std::transform(result.begin(), result.end(), result.begin(), ::towupper);
|
|
return result;
|
|
}
|
|
|
|
std::string ToLowerA(const std::string& str) {
|
|
std::string result = str;
|
|
std::transform(result.begin(), result.end(), result.begin(), ::towlower);
|
|
return result;
|
|
}
|
|
|
|
// 문자열 비교 (왼쪽 n글자)
|
|
bool StartsWith(const std::wstring& str, const std::wstring& prefix) {
|
|
return str.compare(0, prefix.size(), prefix) == 0;
|
|
}
|
|
|
|
// 문자열 포함 여부
|
|
bool Contains(const std::wstring& str, const std::wstring& substr) {
|
|
return str.find(substr) != std::wstring::npos;
|
|
}
|
|
|
|
// 문자열 덧셈
|
|
std::wstring operator+(const std::wstring& a, const char* b) {
|
|
std::wstring wb;
|
|
size_t len = strlen(b);
|
|
wb.resize(len);
|
|
mbstowcs(&wb[0], b, len);
|
|
return a + wb;
|
|
}
|
|
|
|
// 좌우 공백을 제거하는 Trim 함수
|
|
std::wstring Trim(const std::wstring& str)
|
|
{
|
|
auto begin = std::find_if_not(str.begin(), str.end(), iswspace);
|
|
auto end = std::find_if_not(str.rbegin(), str.rend(), iswspace).base();
|
|
|
|
if (begin >= end)
|
|
return L"";
|
|
|
|
return std::wstring(begin, end);
|
|
}
|
|
|
|
void ReplaceAll(std::wstring& message, const std::wstring& pattern, const std::wstring& replace) {
|
|
if (pattern.empty()) return;
|
|
|
|
size_t pos = 0;
|
|
while ((pos = message.find(pattern, pos)) != std::wstring::npos) {
|
|
message.replace(pos, pattern.length(), replace);
|
|
pos += replace.length(); // 바뀐 부분 이후부터 다시 검색
|
|
}
|
|
}
|
|
/**
|
|
* @brief 현재 시간을 ISO 8601 형식의 문자열로 반환하는 API 함수
|
|
* @return "YYYY-MM-DDTHH:MM:SS.ms+HH:MM" 형식의 std::string
|
|
*/
|
|
std::string UtilGetCurrentTimestampISO8601(tm &tm_info)
|
|
{
|
|
|
|
auto now = std::chrono::system_clock::now();
|
|
auto now_c = std::chrono::system_clock::to_time_t(now);
|
|
|
|
//std::tm tm_info;
|
|
#ifdef _WIN32
|
|
localtime_s(&tm_info, &now_c);
|
|
#else
|
|
localtime_r(&now_c, &tm_info);
|
|
#endif
|
|
|
|
auto ms_part = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;
|
|
|
|
int tz_hours = 0;
|
|
int tz_minutes = 0;
|
|
|
|
#ifdef _WIN32
|
|
TIME_ZONE_INFORMATION tzInfo;
|
|
GetTimeZoneInformation(&tzInfo);
|
|
long offset_minutes = -tzInfo.Bias;
|
|
|
|
tz_hours = offset_minutes / 60;
|
|
tz_minutes = abs(offset_minutes % 60);
|
|
#else
|
|
long offset_seconds = tm_info.tm_gmtoff;
|
|
tz_hours = offset_seconds / 3600;
|
|
tz_minutes = abs((offset_seconds % 3600) / 60);
|
|
#endif
|
|
|
|
// 문자열을 저장할 버퍼를 충분한 크기로 준비
|
|
char buffer[100] = { 0, };
|
|
|
|
// snprintf를 사용해 한 번에 문자열 포맷팅
|
|
// chrono::milliseconds::count()는 long long 타입을 반환할 수 있으므로 %lld 사용
|
|
snprintf(buffer, sizeof(buffer),
|
|
"%04d-%02d-%02dT%02d:%02d:%02d.%03lld%+03d:%02d",
|
|
tm_info.tm_year + 1900, tm_info.tm_mon + 1, tm_info.tm_mday,
|
|
tm_info.tm_hour, tm_info.tm_min, tm_info.tm_sec,
|
|
(long long)ms_part.count(), // C++11 표준에 따라 long long으로 캐스팅
|
|
tz_hours,
|
|
tz_minutes);
|
|
|
|
return std::string(buffer);
|
|
}
|
|
|
|
struct EnumData {
|
|
DWORD dwProcessId; // [입력] 찾으려는 프로세스 ID
|
|
HWND hWnd; // [출력] 찾은 윈도우 핸들
|
|
};
|
|
|
|
BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
|
|
{
|
|
EnumData* pData = (EnumData*)lParam;
|
|
DWORD dwProcessId = 0;
|
|
|
|
// 윈도우 핸들로부터 프로세스 ID를 얻습니다.
|
|
GetWindowThreadProcessId(hWnd, &dwProcessId);
|
|
|
|
// 찾으려는 프로세스 ID와 일치하는지 확인합니다.
|
|
if (dwProcessId == pData->dwProcessId)
|
|
{
|
|
// 추가 조건: 화면에 보이고, 소유자가 없는 창을 '메인 윈도우'로 간주합니다.
|
|
if (IsWindowVisible(hWnd) && GetWindow(hWnd, GW_OWNER) == NULL)
|
|
{
|
|
pData->hWnd = hWnd;
|
|
// 찾았으므로 더 이상 열거를 계속할 필요가 없음 (FALSE 반환)
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
// 계속 다음 윈도우를 검색 (TRUE 반환)
|
|
return TRUE;
|
|
}
|
|
|
|
HWND FindMainWindow(DWORD dwProcessId)
|
|
{
|
|
EnumData data;
|
|
data.dwProcessId = dwProcessId;
|
|
data.hWnd = NULL;
|
|
|
|
// 모든 최상위 윈도우를 열거하며 콜백 함수(EnumWindowsProc)를 실행합니다.
|
|
EnumWindows(EnumWindowsProc, (LPARAM)&data);
|
|
|
|
return data.hWnd;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief 지정된 길이의 랜덤 문자열 생성
|
|
* @return "123456678" 형식의 std::wstring
|
|
*/
|
|
std::wstring UtilGenerateRandomString(int length)
|
|
{
|
|
// 랜덤 문자열에 사용할 문자 집합 (알파벳 대소문자 + 숫자)
|
|
const std::wstring charset = L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
|
|
|
// 고품질의 비결정적 시드(seed)를 생성합니다.
|
|
// std::time(0)보다 예측 가능성이 훨씬 낮습니다.
|
|
std::mt19937 rng(static_cast<unsigned long>(
|
|
std::chrono::steady_clock::now().time_since_epoch().count()
|
|
));
|
|
|
|
// 0부터 (문자 집합의 크기 - 1) 사이의 균일한 분포를 설정합니다.
|
|
std::uniform_int_distribution<size_t> distribution(0, charset.length() - 1);
|
|
|
|
std::wstring result;
|
|
result.reserve(length); // 성능을 위해 미리 메모리를 할당합니다.
|
|
|
|
for (int i = 0; i < length; ++i) {
|
|
result += charset[distribution(rng)];
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief 지정된 유니코드 경로의 모든 폴더를 순차적으로 생성합니다. (Windows 전용)
|
|
* 예: C:\Temp\사용자\테스트 경로 입력 시 Temp, 사용자, 테스트 폴더를 차례로 생성합니다.
|
|
* @param path 생성할 전체 디렉토리 경로 (wstring) 입니다.
|
|
* @return true 모든 디렉토리 생성에 성공했거나 이미 존재하는 경우.
|
|
* @return false 디렉토리 생성 중 실패했거나, 경로에 같은 이름의 파일이 있는 경우.
|
|
*/
|
|
bool CreateNestedDirectories(const std::wstring& path)
|
|
{
|
|
|
|
wchar_t full_path[MAX_PATH];
|
|
if (!GetFullPathNameW(path.c_str(), MAX_PATH, full_path, nullptr)) {
|
|
std::wcerr << L"에러: 유효하지 않은 경로입니다. Code: " << GetLastError() << std::endl;
|
|
return false;
|
|
}
|
|
|
|
wchar_t* p = wcschr(full_path, L'\\');
|
|
if (p == nullptr) {
|
|
return true;
|
|
}
|
|
p++;
|
|
|
|
while (p != nullptr && *p != L'\0') {
|
|
p = wcschr(p, L'\\');
|
|
|
|
if (p != nullptr) {
|
|
*p = L'\0'; // 와이드 NULL 문자로 문자열 임시 종료
|
|
}
|
|
|
|
DWORD attributes = GetFileAttributesW(full_path);
|
|
|
|
if (attributes == INVALID_FILE_ATTRIBUTES) {
|
|
if (!CreateDirectoryW(full_path, NULL)) {
|
|
std::wcerr << L"에러: '" << full_path << L"' 디렉토리 생성에 실패했습니다. Code: " << GetLastError() << std::endl;
|
|
if (p != nullptr) *p = L'\\'; // 문자열 복원
|
|
return false;
|
|
}
|
|
std::wcout << L"생성됨: " << full_path << std::endl;
|
|
|
|
}
|
|
else if (!(attributes & FILE_ATTRIBUTE_DIRECTORY)) {
|
|
std::wcerr << L"에러: '" << full_path << L"' 이름으로 파일이 이미 존재합니다." << std::endl;
|
|
if (p != nullptr) *p = L'\\'; // 문자열 복원
|
|
return false;
|
|
}
|
|
|
|
if (p != nullptr) {
|
|
*p = L'\\'; // 잘랐던 문자열 복원
|
|
p++;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* @brief 지정된 이름의 프로세스를 모두 찾아 강제 종료합니다.
|
|
* @param processName 종료할 프로세스의 이름 (예: L"notepad.exe")
|
|
* @return 종료를 시도한 프로세스가 하나라도 있으면 true, 해당 이름의 프로세스를 찾지 못했으면 false를 반환합니다.
|
|
*/
|
|
bool UtilTerminateProcessByName(const std::wstring& processName, uint32_t pid)
|
|
{
|
|
// 현재 시스템의 프로세스 스냅샷을 가져옵니다.
|
|
HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
|
if (hSnapShot == INVALID_HANDLE_VALUE)
|
|
{
|
|
std::wcerr << L"CreateToolhelp32Snapshot failed. Error: " << GetLastError() << std::endl;
|
|
return false;
|
|
}
|
|
|
|
PROCESSENTRY32W pe; // 프로세스 정보를 담을 구조체
|
|
pe.dwSize = sizeof(PROCESSENTRY32W);
|
|
|
|
bool bProcessFound = false;
|
|
|
|
// 첫 번째 프로세스 정보를 가져옵니다.
|
|
if (Process32FirstW(hSnapShot, &pe))
|
|
{
|
|
do
|
|
{
|
|
// 프로세스 이름을 대소문자 구분 없이 비교합니다.
|
|
if (_wcsicmp(pe.szExeFile, processName.c_str()) == 0 && pe.th32ProcessID != pid)
|
|
{
|
|
bProcessFound = true;
|
|
HANDLE hProcess = NULL;
|
|
|
|
// 종료 권한을 가지고 프로세스 핸들을 엽니다.
|
|
hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pe.th32ProcessID);
|
|
|
|
if (hProcess != NULL)
|
|
{
|
|
// 프로세스를 강제 종료합니다. (종료 코드: 1)
|
|
if (TerminateProcess(hProcess, 1))
|
|
{
|
|
std::wcout << L"Process " << processName << L" (PID: " << pe.th32ProcessID << L") terminated." << std::endl;
|
|
}
|
|
else
|
|
{
|
|
std::wcerr << L"Failed to terminate process " << processName << L" (PID: " << pe.th32ProcessID << L"). Error: " << GetLastError() << std::endl;
|
|
}
|
|
|
|
CloseHandle(hProcess); // 핸들을 꼭 닫아줍니다.
|
|
}
|
|
else
|
|
{
|
|
std::wcerr << L"Failed to open process " << processName << L" (PID: " << pe.th32ProcessID << L"). Error: " << GetLastError() << std::endl;
|
|
}
|
|
}
|
|
} while (Process32NextW(hSnapShot, &pe)); // 다음 프로세스 정보를 가져옵니다.
|
|
}
|
|
|
|
CloseHandle(hSnapShot); // 스냅샷 핸들을 꼭 닫아줍니다.
|
|
|
|
if (!bProcessFound)
|
|
{
|
|
std::wcout << L"Process " << processName << L" not found." << std::endl;
|
|
}
|
|
|
|
return bProcessFound;
|
|
}
|
|
|
|
#include <shellapi.h>
|
|
std::wstring UtilGetCommandLineArgment1()
|
|
{
|
|
|
|
std::wstring commandLine = L"";
|
|
LPWSTR cmdLine = GetCommandLineW();
|
|
if (!cmdLine) {
|
|
return L"";
|
|
}
|
|
|
|
int numArgs = 0;
|
|
LPWSTR* argList = CommandLineToArgvW(cmdLine, &numArgs);
|
|
if (!argList) {
|
|
return L"";
|
|
}
|
|
|
|
if (numArgs > 1) {
|
|
commandLine = argList[1];
|
|
}
|
|
|
|
LocalFree(argList);
|
|
return commandLine;
|
|
}
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
NtNameToDosNameW(LPWSTR dosName, SIZE_T size, LPWSTR ntName)
|
|
{
|
|
WCHAR drives[1024] = { 0, };
|
|
WCHAR deviceName[1024] = { 0, };
|
|
WCHAR* name = drives, tmp[3];
|
|
|
|
|
|
int n = GetLogicalDriveStringsW(sizeof(drives), drives);
|
|
if (n >= sizeof(drives) || n == 0)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
while (*name)
|
|
{
|
|
Sleep(1);
|
|
tmp[0] = name[0]; tmp[1] = name[1]; tmp[2] = L'\0';
|
|
|
|
if (!QueryDosDeviceW(tmp, deviceName, sizeof(deviceName)))
|
|
continue;
|
|
|
|
if (wcsncmp(deviceName, ntName, lstrlenW(deviceName)) == 0)
|
|
{
|
|
StringCbCopyW(dosName, size, tmp);
|
|
StringCbCatW(dosName, size, ntName + lstrlenW(deviceName));
|
|
return TRUE;
|
|
}
|
|
|
|
name += lstrlenW(name) + 1;
|
|
}
|
|
|
|
|
|
return FALSE;
|
|
}
|