7.01 버전입니다.
EmEditor 가 더욱 쓸만해지는 모습을 보니 흐뭇하네요. (정품을 사서 그런가 ㅋㅋ)
이제 Hex 에디트 기능만 있으면 딱인데...
헬마입니다.
오랜만에 WinRAR 3.80 베타 버전이 나왔네요.
드디어 ZIP파일에서 유니코드 형식을 지원하네요. UTF8로 인코딩된다는데 이거 다른압축기하고 호환이 될런지 모르겠네요 ㅠㅠ
회사에서 내장 DB를 사용할 일이 생겨서 여기저기 알아보다 보니 SQLite 라는 넘이 제일 간단하면서 편한것 같더군요. 더구나 정적 링크까지 지원해서 따로 DLL을 들고 다닐 필요가 없다는 점도 맘에 들었습니다.
래퍼 클래스들이 몇가지 있는데 이상하게 몇가지 마음에 안드는 것들이 있어서
래퍼 클래스들 2가지를 기반으로 클래스들을 새로 만들었습니다.
CSQLite3.h 파일을 보시면 기반 클래스들의 사이트가 적혀있으니 그것을 봐보시면 쉽게 사용하실 수 있을듯합니다.
기본 사용구조는 MS 의 ADO 와 최대한 비슷하게 해보려고 했습니다.
SQLIte 컴파일 버전 3.5.9 입니다.
DLL들은 Visual Studio 2005 에서 MFC환경에서 컴파일하였습니다.
MFCD - Shard Library
MFCS - Static Library
DD - Debug Dynamic
DS - Debug Static
RD - Release Dynamic
RS - Release Static
이러한 명명규칙으로 파일명이 되어있으니 원하는 것으로 링크하여 사용하시면 됩니다.
헬마입니다.
char tmpBuf[128] = {0,};
// 현재 시간을 초단위로 얻음
__time64_t tmCurrentTime = _time64( NULL );
// 구하려는 시간을 초단위로
__time64_t tmBetweenTime = 100000;
__time64_t tmDestTime = tmCurrentTime - tmBetweenTime;
struct tm *ptmUpTime = _localtime64( &tmDestTime );
strftime( tmpBuf, 128, "%Y-%m-%d %H:%M:%S", ptmUpTime );
2.36 버전이 나온지 근 한달이 되어가는데 이제서야 올리게 되었네요.
이번 버전에도 nsDialogs 가 대폭강화되었습니다.
주문하고 무려 한달이나 기다렸던 책이 드디어 도착했네요.
http://kangcom.com/common/bookinfo/bookinfo.asp?sku=200712080002
인터파크에서 샀는데 거기는 이미지가 없어서 이걸로 링크해봅니다.
고전 명저로 불리는 Programming Applications for Windows 의 5번째 판이구요.
비스타에 맞춰서 내용이 추가/개정 되었더군요.
종이나 이런 책 수준도 깔끔하고 겉표지도 하드커버라 두툼하니 좋네요.
전반적인 내용은 역시나, 프로세스, 스레드, 커널 오브젝트 , 동기화, DLL, 간단한 API 후킹방법 정도인데요. 각 코드나 이런 부분들의 품질이 좋다는게 느껴지네요!
비록 원서지만 사보셔도 내용 이해하는데 전혀 지장없을정도로 코드와 도표등이 많기 때문에 사보시길 추천합니다.
번역서는 나올려나..
헬마입니다.
스프링노트에서 보내기 해봤는데 별로 깔끔하지 않네요.
깔끔하게 보시려면 이쪽으로~~
http://jgh0721.springnote.com/pages/911438
----------------
주로 서비스에서 UI 있는 프로그램을 서비스 세션이 아닌 대화형 데스크탑이 있는 세션에서 실행시킴으로써 정상적으로 작동시키기 위한 것.
부가적으로 이 함수로 실행시키면 비스타의 UAC 를 띄우지 않고 관리자 권한으로 실행시킬 수 있다.
서비스가 SYSTEM 계정으로 실행중이라면 실행시킨 프로그램도 SYSTEM 계정을 받아서 실행됨.
코드 프로젝트의 기사의 소스코드를 기반으로 2000 ~ Vista 에서 작동하도록 수정함.
http://www.codeproject.com/KB/vista-security/VistaSessions.aspx
- #ifdef _UNICODE
#define tstring wstring
#else
#define tstring string
#endif
- // Winlogon.exe 실행파일의 세션을 검색하여 같은 세션에서 실행시킴, 2000 ~ Vista
BOOL LaunchAppIntoDifferentSessionAll(tstring strPath)
{
if( strPath.empty() )
return FALSE;
tstring strSearch;
OSVERSIONINFO osi;
ZeroMemory(&osi,sizeof(OSVERSIONINFO));
osi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osi); - // 변수 선언
BOOL bResult = FALSE;
DWORD dwSessionId = 0; // 세션 ID
DWORD dwWinlogonPID = 0; // Winlogon PID - typedef DWORD (*pfnWTSGetActiveConsoleSessionId)(void);
HMODULE hModule = NULL;
pfnWTSGetActiveConsoleSessionId fnWTSGetActiveConsoleSessionId = NULL; - if( osi.dwMajorVersion == 6 )
{
OutputDebugString(_T("Vista, 라이브러리 로딩 시도"));
hModule = ::LoadLibrary(_T("Kernel32.dll"));
if( hModule != NULL )
{
OutputDebugString(_T("Vista, 함수 로딩 시도"));
fnWTSGetActiveConsoleSessionId = (pfnWTSGetActiveConsoleSessionId) GetProcAddress(hModule, "WTSGetActiveConsoleSessionId");
if( fnWTSGetActiveConsoleSessionId == NULL )
OutputDebugString(_T("WTSGetActiveConsoleSessionId 함수 로딩 실패")); - dwSessionId = fnWTSGetActiveConsoleSessionId();
}
}
// 같은 세션으로 실행할 프로세스 찾기(Winlogon.exe)
BOOL IsExistsWinlogon = FALSE;
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(PROCESSENTRY32);
HANDLE hSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if( hSnap == INVALID_HANDLE_VALUE )
{
bResult = FALSE;
goto CleanUP;
} - if( !Process32First(hSnap, &pe32) )
{
bResult = FALSE;
goto CleanUP;
} - if( osi.dwMajorVersion == 6 )
strSearch = _T("winlogon.exe");
else if( osi.dwMajorVersion == 5 )
strSearch = _T("explorer.exe"); - do
{
if( lstrcmpi(pe32.szExeFile, strSearch.c_str()) == 0 )
{
OutputDebugString(_T("WinLogon 프로세스 검색"));
DWORD dwWLSessionID = 0;
BOOL bRet = ProcessIdToSessionId(pe32.th32ProcessID, &dwWLSessionID); - if( bRet && (osi.dwMajorVersion == 6) && (dwSessionId == dwWLSessionID) )
{
// 비스타
OutputDebugString(_T("Vista"));
dwWinlogonPID = pe32.th32ProcessID;
IsExistsWinlogon = TRUE;
break;
}
else if( bRet && (osi.dwMajorVersion == 5) )
{
// 2000 ~ XP
OutputDebugString(_T("2000/XP"));
dwSessionId = dwWLSessionID;
dwWinlogonPID = pe32.th32ProcessID;
IsExistsWinlogon = TRUE;
break;
}
}
} while ( Process32Next(hSnap, &pe32) ); - if( IsExistsWinlogon == FALSE )
{
OutputDebugString(_T("Winlogon.exe 검색 실패"));
bResult = FALSE;
goto CleanUP;
} - // WINLOGON 프로세스 열고 토큰 복사하여 특정 세션 지정
HANDLE hProcess = ::OpenProcess(MAXIMUM_ALLOWED, FALSE, dwWinlogonPID);
HANDLE hToken = NULL;
HANDLE hTokenDup = NULL;
if( hProcess == NULL )
goto CleanUP;
if( !::OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY|TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY|TOKEN_ADJUST_SESSIONID|TOKEN_READ|TOKEN_WRITE, &hToken))
{
OutputDebugString(_T("OpenProcessToken Failed"));
bResult = FALSE;
goto CleanUP;
}
LUID luid;
if( !LookupPrivilegeValue(NULL,SE_DEBUG_NAME, &luid) )
{
OutputDebugString(_T("LookupPrivilegeValue Failed"));
bResult = FALSE;
goto CleanUP;
}
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if( !DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hTokenDup) )
{
OutputDebugString(_T("DuplicateTokenEx Failed"));
bResult = FALSE;
goto CleanUP;
}
SetTokenInformation(hTokenDup, TokenSessionId, (LPVOID)&dwSessionId, sizeof(DWORD));
if( !AdjustTokenPrivileges(hTokenDup, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL,NULL) )
{
OutputDebugString(_T("AdjustTokenPrivileges Failed"));
bResult = FALSE;
goto CleanUP;
}
if( GetLastError() == ERROR_NOT_ALL_ASSIGNED )
{
OutputDebugString(_T("AdjustTokenPrivileges Assign Failed"));
bResult = FALSE;
goto CleanUP;
} - // CreateProcessAsUser 준비
STARTUPINFO si;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.lpDesktop = _T("winsta0\\default");
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
LPVOID pEnv = NULL;
if( CreateEnvironmentBlock(&pEnv, hTokenDup, TRUE) )
dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
else
pEnv = NULL; - LPTSTR lpszPath = _tcsdup(strPath.c_str());
if( lpszPath == NULL )
{
OutputDebugString(_T("Path String Assign Failed"));
bResult = FALSE;
goto CleanUP;
} - OutputDebugString(lpszPath);
- bResult = ::CreateProcessAsUser(
hTokenDup,
NULL,
lpszPath,
NULL,
NULL,
FALSE,
dwCreationFlags,
pEnv,
NULL,
&si,
&pi); - free(lpszPath);
- if( !bResult )
OutputDebugString(_T("CreateProcessAsUser Failed"));
if( (bResult) && (pi.hProcess != INVALID_HANDLE_VALUE) )
CloseHandle(pi.hProcess);
if( (bResult) && (pi.hThread != INVALID_HANDLE_VALUE) )
CloseHandle(pi.hThread); - CleanUP:
if( hModule )
FreeLibrary(hModule);
if( hSnap != INVALID_HANDLE_VALUE )
CloseHandle(hSnap);
if( hProcess != NULL )
CloseHandle(hProcess);
if( hToken )
CloseHandle(hToken);
if( hTokenDup )
CloseHandle(hTokenDup); - return bResult;
} - BOOL EnablePrivilege(LPCTSTR szPrivilege)
{
BOOL bResult = FALSE;
HANDLE hToken = NULL;
TOKEN_PRIVILEGES tpOld, tpCurrent; - if( !OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken) )
return bResult; - tpCurrent.PrivilegeCount = 1;
tpCurrent.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - if( ::LookupPrivilegeValue(NULL, szPrivilege, &tpCurrent.Privileges[0].Luid) )
{
DWORD dwOld = sizeof(TOKEN_PRIVILEGES);
if( ::AdjustTokenPrivileges(hToken, FALSE, &tpCurrent, dwOld, &tpOld, &dwOld) )
bResult = TRUE;
else
bResult = FALSE;
}
else
bResult = FALSE; - CloseHandle(hToken);
return bResult;
}
이 글은 스프링노트에서 작성되었습니다.
EmEditor 가 7.00.2 버전이 나왔네요.
OutLine 플러그인에서 화면이 깜빡이는 문제를 다수 수정했다고 하네요.
정규표현식 입력 오류를 고쳤는데
정확히 고쳐졌는지 한번 살펴봐주시면 감사합니다.

EmEditor - H.M - Build No. 8 DateTime 2008-06-25.EXE
이올린에 북마크하기
이올린에 추천하기
SQLite.rar