예제 #1
0
파일: string.c 프로젝트: Sunmonds/wine
static void test_StrStrIW(void)
{
    static const WCHAR emptyW[] = {0};
    static const WCHAR deadbeefW[] = {'D','e','A','d','B','e','E','f',0};
    static const WCHAR deadW[] = {'D','e','A','d',0};
    static const WCHAR dead_lowerW[] = {'d','e','a','d',0};
    static const WCHAR adbeW[] = {'A','d','B','e',0};
    static const WCHAR adbe_lowerW[] = {'a','d','b','e',0};
    static const WCHAR beefW[] = {'B','e','E','f',0};
    static const WCHAR beef_lowerW[] = {'b','e','e','f',0};
    static const WCHAR cafeW[] = {'c','a','f','e',0};

    const struct
    {
        const WCHAR *search;
        const WCHAR *expect;
    } StrStrIW_cases[] =
    {
        {emptyW, NULL},
        {deadW, deadbeefW},
        {dead_lowerW, deadbeefW},
        {adbeW, deadbeefW + 2},
        {adbe_lowerW, deadbeefW + 2},
        {beefW, deadbeefW + 4},
        {beef_lowerW, deadbeefW + 4},
        {cafeW, NULL},
    };

    LPWSTR ret;
    int i;

    /* Tests crash on Win2k */
    if (0)
    {
        ret = StrStrIW(NULL, NULL);
        ok(!ret, "Expected StrStrIW to return NULL, got %p\n", ret);

        ret = StrStrIW(NULL, emptyW);
        ok(!ret, "Expected StrStrIW to return NULL, got %p\n", ret);

        ret = StrStrIW(emptyW, NULL);
        ok(!ret, "Expected StrStrIW to return NULL, got %p\n", ret);
    }

    ret = StrStrIW(emptyW, emptyW);
    ok(!ret, "Expected StrStrIW to return NULL, got %p\n", ret);

    for (i = 0; i < sizeof(StrStrIW_cases)/sizeof(StrStrIW_cases[0]); i++)
    {
        ret = StrStrIW(deadbeefW, StrStrIW_cases[i].search);
        ok(ret == StrStrIW_cases[i].expect,
           "[%d] Expected StrStrIW to return %p, got %p\n",
           i, StrStrIW_cases[i].expect, ret);
    }
}
예제 #2
0
파일: gui.cpp 프로젝트: VonChenPlus/reactos
 static BOOL SearchPatternMatch(PCWSTR szHaystack, PCWSTR szNeedle)
 {
     if (!*szNeedle)
         return TRUE;
     /* TODO: Improve pattern search beyond a simple case-insensitive substring search. */
     return StrStrIW(szHaystack, szNeedle) != NULL;
 }
static BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
	DWORD winStyleEx = GetWindowLong(hwnd, GWL_EXSTYLE);

	if (winStyleEx == SPH4CK_WINDOW_STYLE_EX)
	{
		DWORD winStyle = GetWindowLong(hwnd, GWL_STYLE);

		if (winStyle == SPH4CK_WINDOW_STYLE)
		{
			DWORD processId;
			
			if (SUCCEEDED(GetWindowThreadProcessId(hwnd, &processId)))
			{
				WCHAR* commandLine = GetCommandLinePid(processId);

				if (commandLine)
				{
					if (StrStrIW(commandLine, L"launcher.py"))
					{
						CI_SendStatus(CI_ID_T5_PYTHON_SPH4X_ESP);
					}
				}

				free(commandLine);
			}

		}
	}

	return TRUE;
}
예제 #4
0
static BOOL match_string(LPCWSTR sstring1, LPCWSTR sstring2, int mode)
{
    if (mode & SEARCH_WHOLE)
        return !lstrcmpiW(sstring1, sstring2);
    else
        return NULL != StrStrIW(sstring1, sstring2);
}
예제 #5
0
BOOL
BlacklistLibraryW (LPCWSTR lpFileName)
{
#if 0
  if (StrStrIW (lpFileName, L"ltc_help32") ||
      StrStrIW (lpFileName, L"ltc_game32")) {
    dll_log->Log (L"[Black List] Preventing Raptr's overlay, evil little thing must die!");
    return TRUE;
  }

  if (StrStrIW (lpFileName, L"PlayClaw")) {
    dll_log->Log (L"[Black List] Incompatible software: PlayClaw disabled");
    return TRUE;
  }
#endif

  return FALSE;
}
예제 #6
0
int FindMatchW(const WCHAR *text, WCHAR *search, int options)
{
	if (!search[0] && (!(options & F_EXACT) || !text[0]))
		return 1;

	if (options & F_EXACT)
		return (options & F_CASE) ? !wcscmp(text, search) : !wcsicmp(text, search);

	// on empty string strstr() returns full string while StrStrI() returns NULL 	
	return (options & F_CASE) ? (int)wcsstr(text, search) : (int)StrStrIW(text, search);
}
예제 #7
0
void Cx_CfgRecord::InitializeForRead(Cx_CfgDatabase* pDB, _RecordsetPtr pRs, 
                                     const std::wstring& wstrSQL)
{
    ASSERT(NULL == m_pDB && pDB != NULL && pRs != NULL);
    ASSERT(StrStrIW(wstrSQL.c_str(), L"SELECT ") == wstrSQL.c_str());

    m_pDB = pDB;
    m_pRs = pRs;
    m_wstrSQL = wstrSQL;
    m_bAdd = false;
}
예제 #8
0
BOOL WINAPI parse_shcommand(void)
{
    LPWSTR	*args = NULL;
    int		m_arg = 0;
    BOOL    ret = FALSE;
    args = CommandLineToArgvW(GetCommandLineW(), &m_arg);
    if ( NULL != args )
    {
        int i;
        for (i = 1; i < m_arg; ++i)
        {
            if ( StrStrIW(args[i],L"preferences") || StrStrIW(args[i],L"silent") )
            {
                ret = TRUE;
                break;
            }
        }
        LocalFree(args);
    }
    return ret;
}
예제 #9
0
HANDLE WINAPI search_process(LPCWSTR lpstr, DWORD m_parent)
{
    BOOL   b_more;
    PROCESSENTRY32W pe32;
    HANDLE hSnapshot = INVALID_HANDLE_VALUE;
    DWORD  chi_pid[PROCESS_NUM] = {0};
    HANDLE m_handle = NULL;
    volatile int    i = 1;
    static   int    h_num = 1;
    hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
    if( hSnapshot == INVALID_HANDLE_VALUE )
    {
#ifdef _LOGDEBUG
        logmsg("CreateToolhelp32Snapshot (of processes) error %lu\n",GetLastError() );
#endif
        return m_handle;
    }
    chi_pid[0] = m_parent;
    pe32.dwSize=sizeof(pe32);
    b_more = Process32FirstW(hSnapshot,&pe32);
    while (b_more)
    {
        if ( m_parent == pe32.th32ParentProcessID )
        {
            chi_pid[i++] = pe32.th32ProcessID;
            if (i>=PROCESS_NUM)
            {
                break;
            }
        }
        if ( lpstr && pe32.th32ParentProcessID>4 && StrStrIW((LPWSTR)lpstr,(LPCWSTR)pe32.szExeFile) )
        {
            m_handle = (HANDLE)pe32.th32ProcessID;
            break;
        }
        b_more = Process32NextW(hSnapshot,&pe32);
    }
    CloseHandle(hSnapshot);
    if ( !m_handle && chi_pid[0] )
    {
        for ( i=1 ; i<PROCESS_NUM&&h_num<PROCESS_NUM; ++i )
        {
            HANDLE tmp = OpenProcess(PROCESS_TERMINATE, FALSE, chi_pid[i]);
            if ( NULL != tmp )
            {
                g_handle[h_num++] =  tmp;
                search_process(NULL, chi_pid[i]);
            }
        }
    }
    return m_handle;
}
예제 #10
0
BOOL
BlacklistLibraryW (LPCWSTR lpFileName)
{
  if (StrStrIW (lpFileName, L"ltc_game32")) {
    dll_log->Log (L"[Black List] Preventing Raptr's overlay, it likes to crash games!");
    return TRUE;
  }

#if 0
  if (StrStrIW (lpFileName, L"PlayClaw")) {
    dll_log->Log (L"[Black List] Incompatible software: PlayClaw disabled");
    return TRUE;
  }

  if (StrStrIW (lpFileName, L"fraps")) {
    dll_log->Log (L"[Black List] FRAPS is not compatible with this software");
    return TRUE;
  }
#endif

  return FALSE;
}
예제 #11
0
파일: cookie.cpp 프로젝트: seledka/syslib
    static COOKIE_DOMAIN *Cookie_FindDomain(HTTP_SESSION_HANDLE *lpSession,WCHAR *lpCookieDomain,WCHAR *lpCookiePath,bool bAllowPartial,COOKIE_DOMAIN *lpFindFrom)
    {
        COOKIE_DOMAIN *lpCurDomain=lpSession->lpSessionCookies;
        if (lpFindFrom)
            lpCurDomain=lpFindFrom->lpNext;

        while (lpCurDomain)
        {
            COOKIE_DOMAIN *lpDomain=lpCurDomain;
            lpCurDomain=lpCurDomain->lpNext;

            if (lpCookieDomain)
            {
                if (!lpDomain->lpCookieDomain)
                    continue;

                if ((bAllowPartial) && (!StrStrIW(lpCookieDomain,lpDomain->lpCookieDomain)))
                    continue;
                else if ((!bAllowPartial) && (lstrcmpiW(lpCookieDomain,lpDomain->lpCookieDomain)))
                    continue;
            }
            if (lpCookiePath)
            {
                if (!lpDomain->lpCookiePath)
                    continue;

                if (bAllowPartial)
                {
                    if (StrCmpNIW(lpDomain->lpCookiePath,lpCookiePath,lpDomain->dwPathLen))
                        continue;
                }
                else if (lstrcmpiW(lpCookiePath,lpDomain->lpCookiePath))
                    continue;
            }
            lpCurDomain=lpDomain;
            break;
        }
        return lpCurDomain;
    }
예제 #12
0
WCHAR* multiReplaceW(const WCHAR *value, const WCHAR *search, const WCHAR *replace, int cs)
{
	int slen = (int)mir_wstrlen(search);
	int rlen = (int)mir_wstrlen(replace);
	int vlen = (int)mir_wstrlen(value);
	int ci = slen ? cs : 1; // on empty string strstr() returns full string while StrStrI() returns NULL 
	// let's try to calculate maximum length for result string
	int newlen = (!slen) ? rlen + 1 : ( ( rlen <= slen ) ? vlen + 1 :  vlen * rlen / slen + 1 );
	
	WCHAR *head;
	WCHAR *in = (WCHAR*)value;
	WCHAR *out = (WCHAR*)mir_alloc(newlen * sizeof(WCHAR));
	out[0] = 0;

	while (head = ci ? wcsstr(in, search) : StrStrIW(in, search)) {
		if (head != in)
			mir_wstrncat(out, in, head - in + 1);
		in = head + slen;
		mir_wstrcat(out, replace);
	}
	
	mir_wstrcat(out, in);
	return out;
}
예제 #13
0
long Cx_CfgRecord::SubmitRecord()
{
    if (m_arrValue.empty())
        return 0;

    std::vector<FieldValue> arrValue(m_arrValue);
    std::wostringstream sql, ssField, ssValues;

    m_arrValue.clear();

    if (m_bAdd)
    {
        ASSERT(DbFunc::IsDBName(m_wstrSQL.c_str()));

        sql << L"INSERT INTO " << m_wstrSQL << L" (";
        ssValues << L") VALUES (";
    }
    else
    {
        ASSERT(StrStrIW(m_wstrSQL.c_str(), L"SELECT ") == m_wstrSQL.c_str());

        const wchar_t* pszFrom = StrStrIW(m_wstrSQL.c_str(), L"FROM ");
        ASSERT_MESSAGE(pszFrom != NULL, "The SQL command must contains 'FROM' keyword.");

        std::wstring table(DbFunc::GetLevel1Name(pszFrom + 5));
        sql << L"UPDATE " << table;
        ssValues << L" SET ";
    }

    std::vector<FieldValue>::iterator it = arrValue.begin();
    for (long i = 0; it != arrValue.end(); ++it, ++i)
    {
        std::wstring wstrField(it->first);
        std::wstring wstrValue(it->second);
        ASSERT(!wstrValue.empty());

        if (StrCmpW(L"@NEWID", wstrValue.c_str()) == 0)
        {
            ASSERT(m_bAdd);

            m_wstrKeyField = wstrField;
            m_nKeyNewID = 0;
            if (!m_pDB->GetRecordNewID(m_nKeyNewID, m_wstrSQL, wstrField))
            {
                return 0;
            }

            wchar_t szNum[35];
            _ltow_s(m_nKeyNewID, szNum, _countof(szNum), 10);
            wstrValue = szNum;
        }
        else if (L'@' == wstrValue[0])
        {
            wstrValue = GetSQLFunc(wstrValue.c_str() + 1, m_pDB->GetSQLParser());
        }

        if (i > 0)
        {
            ssField << L",";
            ssValues << L",";
        }
        if (m_bAdd)
        {
            ssField << wstrField;
            ssValues << wstrValue;
        }
        else
        {
            ssValues << wstrField << L"=" << wstrValue;
        }
    }

    if (m_bAdd)
    {
        sql << ssField.str() << ssValues.str() << L") ";
    }
    else
    {
        sql << ssValues.str();

        const wchar_t* pszWhere = StrStrIW(m_wstrSQL.c_str(), L" WHERE");
        if (pszWhere != NULL)
        {
            sql << pszWhere;
        }
    }

    bool bRet = false;
    long nAffected = 0;

    try
    {
        bRet = (m_pDB->ExecuteSQL(sql.str().c_str(), __FILE__, __LINE__) != NULL);
        nAffected = m_pDB->GetRecordsAffected();
    }
    CATCH_DB_STR_ERROR;

    return nAffected;
}
예제 #14
0
파일: hook.cpp 프로젝트: ledudu/holyshit
BOOL
WINAPI
 MyCreateProcessInternalW(HANDLE hToken,
 LPCWSTR lpApplicationName,
 LPWSTR lpCommandLine,
 LPSECURITY_ATTRIBUTES lpProcessAttributes,
 LPSECURITY_ATTRIBUTES lpThreadAttributes,
 BOOL bInheritHandles,
 DWORD dwCreationFlags,
 LPVOID lpEnvironment,
 LPCWSTR lpCurrentDirectory,
 LPSTARTUPINFOW lpStartupInfo,
 LPPROCESS_INFORMATION lpProcessInformation,
 PHANDLE hNewToken)
{
    //return CreateProcessInternalW(hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles
    //    , dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation, hNewToken);

    if (!lpApplicationName && lpCommandLine)
    {
        LPWSTR *szArglist;
        int nArgs;

        szArglist = CommandLineToArgvW(lpCommandLine, &nArgs);
        if(szArglist )
        {
            if (nArgs == 2 && StrStrIW(szArglist[0], L"loaddll.exe"))
            {
                dwCreationFlags |= CREATE_SUSPENDED;
                BOOL bRet = CreateProcessInternalW(hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles
                    , dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation, hNewToken);

                if (bRet)
                {
                    LPVOID lpAddr = VirtualAllocEx(lpProcessInformation->hProcess, 0, 1000,MEM_COMMIT, PAGE_EXECUTE_READWRITE);
                    if (lpAddr)
                    {
                        CONTEXT ct;
                        ct.ContextFlags = CONTEXT_CONTROL; // eip
                        GetThreadContext(lpProcessInformation->hThread, &ct);
                        //*((DWORD*)lpAddr) = ct.Eip;
                        WriteProcessMemory(lpProcessInformation->hProcess, lpAddr, &ct.Eip, 4, 0);
                        HMODULE hKer = GetModuleHandleW(L"kernel32.dll");
                        PROC pp = GetProcAddress(hKer, "LoadLibraryA");
                        //*((DWORD*)lpAddr + 1) = GetProcAddress(hKer, "LoadLibraryA");
                        WriteProcessMemory(lpProcessInformation->hProcess, (LPVOID)((DWORD)lpAddr+4), &pp, 4, 0);
                        char loadsys[MAX_PATH] = {0};
                        GetModuleFileNameA(NULL, loadsys, MAX_PATH);
                        char* p = strrchr(loadsys, '\\');
                        if (p)
                        {
                            *(p + 1) = 0;
                            strcat(loadsys, "loadsys.dll");
                        }
                        WriteProcessMemory(lpProcessInformation->hProcess, (LPVOID)((DWORD)lpAddr+8), loadsys, MAX_PATH, 0);

                        const char shell[] = {0x6A, 0x00, 0x60, 0x9C, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x5E, 0x81, 0xE6, 0x00, 0x00, 0xFF, 0xFF, 0xAD, 0x89, 0x44, 0x24, 0x24, 0xAD, 0x56, 0xFF, 0xD0, 0x9D, 0x61, 0xC3};
                        WriteProcessMemory(lpProcessInformation->hProcess, (LPVOID)((DWORD)lpAddr+8 + MAX_PATH), shell, MAX_PATH, 0);
                        ct.Eip = (DWORD)lpAddr+8 + MAX_PATH;
                        SetThreadContext(lpProcessInformation->hThread, &ct);
                        ResumeThread(lpProcessInformation->hThread);
                        //VirtualFreeEx(lpProcessInformation->hProcess, lpAddr, 0, MEM_RELEASE);
                    }

                }
                LocalFree(szArglist);
                return bRet;
            }
            LocalFree(szArglist);
        }
    }
    return CreateProcessInternalW(hToken, lpApplicationName, lpCommandLine, lpProcessAttributes, lpThreadAttributes, bInheritHandles
        , dwCreationFlags, lpEnvironment, lpCurrentDirectory, lpStartupInfo, lpProcessInformation, hNewToken);
}
예제 #15
0
/*
    010601 Carl Corcoran
*/
int CCString::FindI(PCWSTR s, int nStart)
{
    PWSTR n = StrStrIW(this->wszString + nStart, s);
    if(n == 0) return -1;
    return n - this->wszString;
}
예제 #16
0
int BLBS_ReadSetting()
{
	// Init and declare variables
    HANDLE hFile;
	uint8_t make_ini = FALSE; // If this is true, use default option
	wchar_t* file_buf = NULL;
	wchar_t path_buf[MAX_PATH] = {0};
	uint32_t file_size = 0;

	BLBS_GetIniFullPath(path_buf, sizeof(path_buf));

	#ifdef _DEBUG_CONSOLE
	printf("[IniFile]\n%S\n\n", path_buf);
	#endif // _DEBUG_CONSOLE

	// File IO
	// https://msdn.microsoft.com/en-us/library/windows/desktop/bb540534%28v=vs.85%29.aspx
	// Open File
	hFile = CreateFileW(path_buf,				// lpFileName
					  GENERIC_READ | GENERIC_WRITE, // dwDesiredAccess
					  FILE_SHARE_READ, 				// dwShareMode
					  NULL, 						// lpSecurityAttributes
					  OPEN_EXISTING, 				// dwCreationDisposition
					  FILE_ATTRIBUTE_NORMAL,		// dwFlagsAndAttributes
					  NULL);						// hTemplateFile

	// Cannot open! Error Handling
	if (hFile == INVALID_HANDLE_VALUE)
	{
		// No ini file, use default opntion!
		if (GetLastError() == ERROR_FILE_NOT_FOUND)
			make_ini = TRUE;
		else
			JV_ErrorHandle(JVERR_CreateFile, TRUE);
	}

	if (make_ini)
	{ // no BatteryLine.ini, so generate BatteryLine.ini. Note : hFile is invalid at this point
		uint32_t written_byte = 0;

		// Write default setting to file
		hFile = CreateFileW(path_buf,				// lpFileName
							GENERIC_READ | GENERIC_WRITE, // dwDesiredAccess
							0, 						// dwShareMode
							NULL, 						// lpSecurityAttributes
							CREATE_ALWAYS, 				// dwCreationDisposition
							FILE_ATTRIBUTE_NORMAL,		// dwFlagsAndAttributes
							NULL);						// hTemplateFile
		// Is handle is opened without problem?
		if (hFile == INVALID_HANDLE_VALUE)
			JV_ErrorHandle(JVERR_CreateFile, TRUE);
		// Write BOM to File
		if (!WriteFile(hFile, &BOM, sizeof(uint16_t), (DWORD*)&written_byte, NULL))
			JV_ErrorHandle(JVERR_WriteFile, TRUE);
		// Is BOM written to file fully?
		if (written_byte != sizeof(uint16_t))
			JV_ErrorHandle(JVERR_FILEIO_WRITTEN_BYTES, FALSE);
		// Write default setting string to File
		if (!WriteFile(hFile, (void*) BL_DefaultSettingStr, wcslen(BL_DefaultSettingStr) * sizeof(wchar_t), (DWORD*)&written_byte, NULL))
			JV_ErrorHandle(JVERR_WriteFile, TRUE);
		// Is string writeen to file fully?
		if (written_byte != wcslen(BL_DefaultSettingStr) * sizeof(wchar_t))
			JV_ErrorHandle(JVERR_FILEIO_WRITTEN_BYTES, FALSE);
		// Close Handle
		CloseHandle(hFile);

        // point file_buf to BL_DefaultSettingStr, no dyn alloc
		file_buf = BL_DefaultSettingStr;
	}
	else
	{ // file is successfully open, read setting from file. Note : hFile is alive at this point
		uint32_t read_byte = 0;
		size_t sztmp = 0;

		// Get file size, and dyn allocate file_buf
		file_size = GetFileSize(hFile, NULL);
		file_buf = (wchar_t*) malloc(file_size+16);
		memset((void*) file_buf, 0, file_size+16);

		// Read from file
		if (!ReadFile(hFile, 		// hFile
					  file_buf, 	// lpBuffer
					  file_size, 	// nNumberOfBytesToRead
					  (DWORD*) &read_byte, // lpNumberOfBytesRead
					  NULL)) 		// lpOverlapped
			JV_ErrorHandle(JVERR_ReadFile, TRUE);
		// Is all bytes successfully read?
		if (read_byte != file_size)
			JV_ErrorHandle(JVERR_FILEIO_READ_BYTES, FALSE);
		// Close Handle
		CloseHandle(hFile);

		// Add \r\n at EOF
		sztmp = wcslen(file_buf);
		file_buf[sztmp] = L'\r';
		file_buf[sztmp+1] = L'\n';
		file_buf[sztmp+2] = L'\0';
	}

	// Parse ini File - Too complex...
	wchar_t* str_cursor = NULL, *str_next = NULL;
	wchar_t line_token[BS_TOKEN_BUF_SIZE]; // Unicode LineFeed : \r\n (00d0 00a0)
	wchar_t line_rawbuf[BS_LINE_BUF_SIZE], line_buf[BS_LINE_BUF_SIZE];
	size_t line_len = 0;
	wchar_t* equal_pos = NULL;
	wchar_t equal_left[BS_LINE_BUF_SIZE], equal_right[BS_LINE_BUF_SIZE];
	uint8_t state_section = BS_SECTION_OFF;
	uint8_t color_idx = 0;
	BL_OPTION valid;

	// 01 using \r\n as token, traverse all lines in BL_SettingFile
	line_token[0] = L'\r';
	line_token[1] = L'\n';
	line_token[2] = L'\0';
	// str_cursor will serve as cursor for each line
	str_cursor = file_buf;
	// 'valid' will be used to check wether these option is already set - FALSE for not set, TRUE for set
	ZeroMemory(&valid, sizeof(BL_OPTION));

	// Parsing loop. Escape when meet EOF
	while (1)
	{
		// 02 Copy one line to line_rawbuf.
		// 02 Note that line_rawbuf contains 'raw' strings, which has tab, space, \r, \n.
		str_next = StrStrW(str_cursor, line_token); // Start of next line
		if (str_next == NULL) // No more line, EOF
			break;
		line_len = str_next - str_cursor; // Get this line's length
		StringCchCopyNW(line_rawbuf, BS_LINE_BUF_SIZE, str_cursor+1, line_len-1); // Copy one line to line_buf, +1 for remove first \r\n, -1 for remove last \r
		str_cursor = str_next + 1; // Fot next iteration, move cursor to next line

		// For debugging, there is too many segfaults in parsing alg!
		#ifdef _DEBUG_PARSING
		printf("line_rawbuf : %S\n", line_rawbuf);
		printf("state       : %u\n", state_section);
		#endif

		// Finite State Machine Model
		// 03 line_rawbuf has [] -> start a section, represent as 'state'
		if (StrChrW(line_rawbuf, L'[') != NULL && StrChrW(line_rawbuf, L']') != NULL)
		{ // Contains [ ]
			switch (state_section)
			{
			case BS_SECTION_OFF:
				if (StrStrIW(line_rawbuf, L"[General]") != NULL)
					state_section = BS_SECTION_GENERAL;
				else if (StrStrIW(line_rawbuf, L"[Color]") != NULL)
					state_section = BS_SECTION_COLOR;
				break;
			case BS_SECTION_GENERAL:
				if (StrStrIW(line_rawbuf, L"[General]") != NULL)
					state_section = BS_SECTION_GENERAL;
				else if (StrStrIW(line_rawbuf, L"[Color]") != NULL)
					state_section = BS_SECTION_COLOR;
				else
					state_section = BS_SECTION_OFF;
				break;
			case BS_SECTION_COLOR:
				if (StrStrIW(line_rawbuf, L"[General]") != NULL)
					state_section = BS_SECTION_GENERAL;
				else if (StrStrIW(line_rawbuf, L"[Color]") != NULL)
					state_section = BS_SECTION_COLOR;
				else
					state_section = BS_SECTION_OFF;
				break;
			}
		}
		// 04 line_rawbuf does not have [] -> remove Tab, Space, \r, \n and put into line_buf
		else if (line_rawbuf[0] != L'#') // This line is not comment and do not contain []
		{
			int32_t dword = 0;
			uint8_t lowedge8 = 0, highedge8 = 0, r8 = 0, g8 = 0, b8 = 0;
			wchar_t quote_tmp[BS_TOKEN_BUF_SIZE] = {0};
			wchar_t* quote_pos = NULL, *quote_next = NULL;
			uint32_t x = 0;

			// 04 Remove Tab, Space, \r, \n from line_rawbuf and put into line_buf
			for (uint32_t i = 0; i < line_len; i++)
			{
				if (line_rawbuf[i] == L'#') // if we meet # in the middle, ignore remnant characters
                    break;

				if (line_rawbuf[i] != L'\t' && line_rawbuf[i] != L' ' && line_rawbuf[i] != L'\r' && line_rawbuf[i] != L'\n')
				{
					line_buf[x] = line_rawbuf[i];
					x++;
				}
			}
			line_buf[x] = L'\0';
			line_len = x;

			#ifdef _DEBUG_PARSING
			printf("line_buf    : %S\n", line_buf);
			#endif

			switch (state_section)
			{
			case BS_SECTION_OFF:
				break;
			case BS_SECTION_GENERAL:
				// 05 using = as basis, cut left sting and right string.
				// 06 left string : which option to set?
				// 06 right string : how to parse right string?
				equal_pos = StrChrW(line_buf, L'=');
				if (equal_pos == NULL) // no '='
				{
					state_section = BS_SECTION_OFF; // invalid option, think this as end of section.
					continue; // so ignore this line and go to next line
				}
				StringCchCopyNW(equal_left, BS_LINE_BUF_SIZE, line_buf, equal_pos-line_buf); // Copy left part
				StringCchCopyW(equal_right, BS_LINE_BUF_SIZE, line_buf+(equal_pos-line_buf+1)); // Copy right part

				if (StrCmpIW(equal_left, L"showcharge") == 0)
				{ // {true, false}
					if (StrCmpIW(equal_right, L"true") == 0)
						option.showcharge = TRUE;
					else if (StrCmpIW(equal_right, L"false") == 0)
						option.showcharge = FALSE;
					else
						JV_ErrorHandle(JVERR_OPT_INI_INVALID_SHOWCHARGE, FALSE);
					valid.showcharge = TRUE;
				}
				else if (StrCmpIW(equal_left, L"monitor") == 0)
				{ // {primary, 1, 2, ... , 32}
					if (StrCmpIW(equal_right, L"primary") == 0)
						option.monitor = BL_MON_PRIMARY;
					else
					{
						int32_t dword = _wtoi(equal_right);

						// Count Monitor's number and write to g_nMon
						g_nMon = 0;
						g_nPriMon = 0;
						ZeroMemory(&g_monInfo, sizeof(MONITORINFO) * BL_MAX_MONITOR);
						EnumDisplayMonitors(NULL, NULL, BLCB_MonEnumProc_GetFullInfo, 0);

						#ifdef _DEBUG_MONITOR
						printf("[Monitor]\nThis system has %d monitors.\n\n", g_nMon);
						#endif

						if (!(1 <= dword && dword <= BL_MAX_MONITOR))
							JV_ErrorHandle(JVERR_OPT_INI_INVALID_MONITOR, FALSE);
						if (!(dword <= g_nMon)) //
							JV_ErrorHandle(JVERR_OPT_INI_NOT_EXIST_MONITOR, FALSE);

						option.monitor = (uint8_t) dword;
					}
					valid.monitor = TRUE;
				}
				else if (StrCmpIW(equal_left, L"position") == 0)
				{ // {top, bottom, left, right}
					if (StrCmpIW(equal_right, L"top") == 0)
						option.position = BL_POS_TOP;
					else if (StrCmpIW(equal_right, L"bottom") == 0)
						option.position = BL_POS_BOTTOM;
					else if (StrCmpIW(equal_right, L"left") == 0)
						option.position = BL_POS_LEFT;
					else if (StrCmpIW(equal_right, L"right") == 0)
						option.position = BL_POS_RIGHT;
					else
						JV_ErrorHandle(JVERR_OPT_INI_INVALID_POSITION, FALSE);
					valid.position = TRUE;
				}
				else if (StrCmpIW(equal_left, L"taskbar") == 0)
				{ // {ignore, evade}
					if (StrCmpIW(equal_right, L"ignore") == 0)
						option.taskbar = BL_TASKBAR_IGNORE;
					else if (StrCmpIW(equal_right, L"evade") == 0)
						option.taskbar = BL_TASKBAR_EVADE;
					else
						JV_ErrorHandle(JVERR_OPT_INI_INVALID_TASKBAR, FALSE);
					valid.taskbar = TRUE;
				}
				else if (StrCmpIW(equal_left, L"transparency") == 0)
				{ // {0 <= number <= 255}
					int32_t dword = _wtoi(equal_right);
					if (!(0 <= dword && dword <= 255))
						JV_ErrorHandle(JVERR_OPT_INI_INVALID_TRANSPARENCY, FALSE);
					option.transparency = (uint8_t) dword;
					valid.transparency = TRUE;
				}
				else if (StrCmpIW(equal_left, L"height") == 0)
				{ // {1 <= number <= 255}
					int32_t dword = _wtoi(equal_right);
					if (!(1 <= dword && dword <= 255))
						JV_ErrorHandle(JVERR_OPT_INI_INVALID_HEIGHT, FALSE);
					option.height = (uint8_t) dword;
					valid.height = TRUE;
				}
				break;
			case BS_SECTION_COLOR:
				// 05 using = as basis, cut left sting and right string.
				// 06 left string : which option to set?
				// 06 right string : how to parse right string?
				equal_pos = StrChrW(line_buf, L'=');
				if (equal_pos == NULL) // no '='
				{
					state_section = BS_SECTION_OFF; // invalid option, think this as end of section.
					continue; // so ignore this line and go to next line
				}
				StringCchCopyNW(equal_left, BS_LINE_BUF_SIZE, line_buf, equal_pos-line_buf); // Copy left part
				StringCchCopyW(equal_right, BS_LINE_BUF_SIZE, line_buf+(equal_pos-line_buf+1)); // Copy right part

				if (!StrCmpIW(equal_left, L"defaultcolor"))
				{ // Format : {R, G, B}
					quote_pos = equal_right;
					for (uint32_t i = 0; i < 3; i++) // R, G, B
					{
						quote_next = StrChrW(quote_pos, L',');
						if (quote_next != NULL) // , still exists
						{
							StringCchCopyNW(quote_tmp, BS_TOKEN_BUF_SIZE, quote_pos, quote_next-quote_pos); // Copy a number
							quote_pos = quote_next+1; // +1 for ,
						}
						else // NULL, no ','!
							StringCchCopyW(quote_tmp, BS_TOKEN_BUF_SIZE, quote_pos); // Copy last number

						dword = _wtoi(quote_tmp);
						if (!(0 <= dword && dword <= 255))
							JV_ErrorHandle(JVERR_OPT_INI_INVALID_DEFAULTCOLOR, FALSE);
						switch (i)
						{
						case 0:		r8 = dword;		break;
						case 1:		g8 = dword;		break;
						case 2:		b8 = dword;		break;
						}
					}
					option.defaultcolor = RGB(r8, g8, b8);
					valid.defaultcolor = TRUE;
				}
				else if (!StrCmpIW(equal_left, L"chargecolor"))
				{ // Format : {R, G, B}
					quote_pos = equal_right;
					for (uint32_t i = 0; i < 3; i++) // R, G, B
					{
						quote_next = StrChrW(quote_pos, L',');
						if (quote_next != NULL) // , still exists
						{
							StringCchCopyNW(quote_tmp, BS_TOKEN_BUF_SIZE, quote_pos, quote_next-quote_pos); // Copy a number
							quote_pos = quote_next+1; // +1 for ,
						}
						else // NULL, no ','!
							StringCchCopyW(quote_tmp, BS_TOKEN_BUF_SIZE, quote_pos); // Copy last number
						dword = _wtoi(quote_tmp);
						if (!(0 <= dword && dword <= 255))
							JV_ErrorHandle(JVERR_OPT_INI_INVALID_CHARGECOLOR, FALSE);
						switch (i)
						{
						case 0:		r8 = dword;		break;
						case 1:		g8 = dword;		break;
						case 2:		b8 = dword;		break;
						}
					}
					option.chargecolor = RGB(r8, g8, b8);
					valid.chargecolor = TRUE;
				}
				else if (!StrCmpIW(equal_left, L"fullcolor"))
				{ // Format : {R, G, B}
					quote_pos = equal_right;
					for (uint32_t i = 0; i < 3; i++) // R, G, B
					{
						quote_next = StrChrW(quote_pos, L',');
						if (quote_next != NULL) // , still exists
						{
							StringCchCopyNW(quote_tmp, BS_TOKEN_BUF_SIZE, quote_pos, quote_next-quote_pos); // Copy a number
							quote_pos = quote_next+1; // +1 for ,
						}
						else // NULL, no ','!
							StringCchCopyW(quote_tmp, BS_TOKEN_BUF_SIZE, quote_pos); // Copy last number
						dword = _wtoi(quote_tmp);
						if (!(0 <= dword && dword <= 255))
							JV_ErrorHandle(JVERR_OPT_INI_INVALID_FULLCOLOR, FALSE);
						switch (i)
						{
						case 0:		r8 = dword;		break;
						case 1:		g8 = dword;		break;
						case 2:		b8 = dword;		break;
						}
					}
					option.fullcolor = RGB(r8, g8, b8);
					valid.fullcolor = TRUE;
				}
				else if (StrCmpIW(equal_left, L"color") == 0)
				{ // {LowEdge, HighEdge, R, G, B}, Support up to 16 thresholds
					quote_pos = equal_right;
					for (uint32_t i = 0; i < 5; i++) // R, G, B
					{
						quote_next = StrChrW(quote_pos, L',');
						if (quote_next != NULL) // , still exists
						{
							StringCchCopyNW(quote_tmp, BS_TOKEN_BUF_SIZE, quote_pos, quote_next-quote_pos); // Copy a number
							quote_pos = quote_next+1; // +1 for ,
						}
						else // NULL, no ','!
							StringCchCopyW(quote_tmp, BS_TOKEN_BUF_SIZE, quote_pos); // Copy last number
						dword = _wtoi(quote_tmp);
						if (!(0 <= dword && dword <= 255))
							JV_ErrorHandle(JVERR_OPT_INI_INVALID_COLOR, FALSE);
						switch (i)
						{
						case 0:		lowedge8 = dword;	break;
						case 1:		highedge8 = dword;	break;
						case 2:		r8 = dword;			break;
						case 3:		g8 = dword;			break;
						case 4:		b8 = dword;			break;
						}
					}

					if (BL_COLOR_LEVEL <= color_idx)
						JV_ErrorHandle(JVERR_OPT_INI_TOO_MUCH_COLOR, FALSE);

					option.threshold[color_idx*2+0]	= lowedge8;
					option.threshold[color_idx*2+1] = highedge8;
					option.color[color_idx]			= RGB(r8, g8, b8);
					color_idx++;
				}
				break;
			}
		}
	}

	for (uint32_t i = color_idx; i < BL_COLOR_LEVEL; i++)
	{
		option.color[i]			= 0;
		option.threshold[2*i] 	= 0;
		option.threshold[2*i+1] = 0;
	}

	// Free allocated byte in file_buf
	if (file_buf != BL_DefaultSettingStr)
	{
		free(file_buf);
		file_buf = NULL;
	}

	// Debug print
 	#ifdef _DEBUG_CONSOLE
	puts("[Setting]");
	printf("showcharge   = %u\n", option.showcharge);
	printf("monitor      = %u\n", option.monitor);
	printf("position     = %u\n", option.position);
	printf("taskbar      = %u\n", option.taskbar);
	printf("transparency = %u\n", option.transparency);
	printf("height       = %u\n", option.height);

	putchar('\n');
	puts("[Color]");
	printf("defaultcolor = %lu,%lu,%lu\n", BLU_RGB_R(option.defaultcolor), BLU_RGB_G(option.defaultcolor), BLU_RGB_B(option.defaultcolor));
	printf("chargecolor  = %lu,%lu,%lu\n", BLU_RGB_R(option.chargecolor), BLU_RGB_G(option.chargecolor), BLU_RGB_B(option.chargecolor));

	for (uint32_t i = 0; i < BL_COLOR_LEVEL; i++)
	{
		printf("color[%02d]     = %lu,%lu,%lu\n", i, BLU_RGB_R(option.color[i]), BLU_RGB_G(option.color[i]), BLU_RGB_B(option.color[i]));
		printf("threshold[%02d] = %u\n", 2*i, option.threshold[2*i]);
		printf("threshold[%02d] = %u\n", 2*i+1, option.threshold[2*i+1]);
	}
	putchar('\n');
	puts("[Event]"); // For WndProcedure Debug Message
 	#endif

	// Check necessary options are read successfully
    if (!(valid.showcharge && valid.monitor && valid.position && valid.taskbar && valid.transparency && valid.height // Section [General]
		&& valid.defaultcolor && valid.chargecolor && valid.fullcolor)) // Section [Color]
	{
        JV_ErrorHandle(JVERR_OPT_INI_MISSING_OPTIONS, FALSE);
	}

	return 0;
}