BSOne.SFC/Tocsg.Module/Bs1Flt/dist/BSone_util.cpp

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;
}