コード例 #1
0
ファイル: StringCchCopyNW-t.c プロジェクト: JSund/libstrsafe
int main(void){
    wchar_t dest[11];
    wchar_t dest2[11];
    
    plan(9);

    ok(SUCCEEDED(StringCchCopyNW(dest, 11, L"test", 4)),
            "Copy entire string.");
    is_wstring(L"test", dest,
            "Result of copying entire string.");

    ok(SUCCEEDED(StringCchCopyNW(dest2, 11, dest, 11)),
            "Copy from buffer with additional capacity.");
    is_wstring(L"test", dest2,
            "Result of copying from buffer with additional capacity.");

    ok(SUCCEEDED(StringCchCopyNW(dest, 11, L"", 1)),
            "Copy empty string.");
    is_wstring(L"", dest,
            "Result of copying empty string.");
    
    ok(StringCchCopyNW(dest, 11, L"longer string", 12) ==
            STRSAFE_E_INSUFFICIENT_BUFFER,
            "Copy a string that is too long.");
    is_wstring(L"longer str", dest,
            "Result of copying a string that is too long.");
    
    ok(StringCchCopyNW(dest, 0, L"test", 4) ==
            STRSAFE_E_INVALID_PARAMETER,
            "Make sure error is thrown if cchDest is zero.");

    return 0;
}
コード例 #2
0
IFACEMETHODIMP ContextMenu::GetCommandString(UINT_PTR idCommand,
                                             UINT uFlags,
                                             LPUINT lpReserved,
                                             LPSTR pszName,
                                             UINT uMaxNameLen)
{
    HRESULT  hr = E_INVALIDARG;

    if (idCommand != IDM_SHAREWITHBOX)
    {
        return hr;
    }

    switch(uFlags)
    {
        case GCS_HELPTEXTA:
            hr = StringCchCopyNA(pszName, 
                                 uMaxNameLen, 
                                 HELP_A, 
                                 uMaxNameLen);
            break; 

        case GCS_HELPTEXTW: 
            hr = StringCchCopyNW((LPWSTR)pszName, 
                                 uMaxNameLen, 
                                 HELP_W, 
                                 uMaxNameLen);
            break; 

        case GCS_VERBA:
            hr = StringCchCopyNA(pszName, 
                                  uMaxNameLen, 
                                  VERB_A, 
                                  uMaxNameLen);
            break; 

        case GCS_VERBW:
            hr = StringCchCopyNW((LPWSTR)pszName, 
                                 uMaxNameLen, 
                                 VERB_W, 
                                 uMaxNameLen);
            break; 

        default:
            hr = S_OK;
            break; 
    }
    return hr;
}
コード例 #3
0
ファイル: DrmShlExt.cpp プロジェクト: Ochieng/drm
//
//   FUNCTION: CDrmShlExt::GetCommandString(UINT, UINT, LPUINT, 
//             LPSTR, UINT)
//
//   PURPOSE: If a user highlights one of the items added by a context menu 
//            handler, the handler's IContextMenu::GetCommandString method is 
//            called to request a Help text string that will be displayed on 
//            the Windows Explorer status bar. This method can also be called 
//            to request the verb string that is assigned to a command. 
//            Either ANSI or Unicode verb strings can be requested.
//
IFACEMETHODIMP CDrmShlExt::GetCommandString(
    UINT_PTR idCommand, UINT uFlags, LPUINT lpReserved, LPSTR pszName, 
    UINT uMaxNameLen)
{
    HRESULT hr = E_INVALIDARG;

    // For the command "&Decrypt" (IDM_DECRYPT)
    if (idCommand == IDM_DECRYPT)
    {
        switch (uFlags)
        {
        case GCS_HELPTEXTA:
            hr = StringCchCopyNA(pszName, 
                lstrlenA(pszName) / sizeof(pszName[0]), 
                "Rights Network File Decrypter", 
                uMaxNameLen);
            break;

        case GCS_HELPTEXTW:
            hr = StringCchCopyNW((LPWSTR)pszName, 
                lstrlenW((LPWSTR)pszName) / sizeof(pszName[0]), 
                L"Rights Network File Decrypter", 
                uMaxNameLen);
            break;

        case GCS_VERBA:
            hr = StringCchCopyNA(pszName, 
                lstrlenA(pszName) / sizeof(pszName[0]), 
                VERB_DECRYPTA, uMaxNameLen);
            break;

        case GCS_VERBW:
            hr = StringCchCopyNW((LPWSTR)pszName, 
                lstrlenW((LPWSTR)pszName) / sizeof(pszName[0]), 
                VERB_DECRYPTW, uMaxNameLen);
            break;

        default:
            hr = S_OK;
        }
    }

    // If the command (idCommand) is not supported by this context menu 
    // extension handler, return E_INVALIDARG.

    return hr;
}
コード例 #4
0
ファイル: consoleargs.cpp プロジェクト: l1183479157/coreclr
size_t SafeStrCopy( _In_ LPCWSTR wszSrc, _In_ size_t cchSrc, _Out_ LPWSTR wszDest, _In_ size_t cchDest)
{
    if (cchSrc == (size_t)-1)
        cchSrc = wcslen(wszSrc);

    if (cchSrc >= cchDest) {
        SetLastError(ERROR_FILENAME_EXCED_RANGE);
        return 0;
    }

    if (FAILED(StringCchCopyNW( wszDest, cchDest, wszSrc, cchSrc))) {
        SetLastError(ERROR_FILENAME_EXCED_RANGE);
        return 0;
    }
    return cchSrc;
}
コード例 #5
0
ファイル: filedefext.cpp プロジェクト: RareHare/reactos
BOOL
CFileDefExt::InitFilePath(HWND hwndDlg)
{
    /* Find the filename */
    WCHAR *pwszFilename = PathFindFileNameW(m_wszPath);

    if (pwszFilename > m_wszPath)
    {
        /* Location field */
        WCHAR wszLocation[MAX_PATH];
        StringCchCopyNW(wszLocation, _countof(wszLocation), m_wszPath, pwszFilename - m_wszPath);
        PathRemoveBackslashW(wszLocation);

        SetDlgItemTextW(hwndDlg, 14009, wszLocation);
    }

    /* Filename field */
    SetDlgItemTextW(hwndDlg, 14001, pwszFilename);

    return TRUE;
}
コード例 #6
0
ファイル: Registry.cpp プロジェクト: msuiche/SwishDbgExt
vector<KEY_NAME>
GetKeysNames(
    _In_ PWSTR FullKeyPath
    )
{
    vector<KEY_NAME> SubKeysNames;
    KEY_NAME KeyName;
    PWSTR CurrentName;
    PWSTR RemainingName;
    ULONG Length;

    CurrentName = FullKeyPath;
    RemainingName = FullKeyPath;

    while (*CurrentName) {

        CurrentName++;
        RemainingName++;

        while (*RemainingName && (*RemainingName != L'\\')) {

            RemainingName++;
        }

        Length = (ULONG)(RemainingName - CurrentName);

        if (Length) {

            StringCchCopyNW(KeyName.Name, _countof(KeyName.Name), CurrentName, Length);

            SubKeysNames.push_back(KeyName);
        }

        CurrentName = RemainingName;
    }

    return SubKeysNames;
}
コード例 #7
0
ファイル: util.c プロジェクト: 340211173/Driver
DWORD
WINAPI
RemoveVirtualDriver (
                     HWND           hWnd,
                     PVIRT_DEVICE   pVirtualDevice,
                     ULONG          BusNumber)
{
    HANDLE                      hDevice = INVALID_HANDLE_VALUE;
    ULONG                       ulStrLen = 0;
    size_t                      retVal = 0;
    UCHAR                       BusName[16] = "\\\\.\\1394BUS";
    PIEEE1394_API_REQUEST       p1394ApiReq = NULL;
    PIEEE1394_VDEV_PNP_REQUEST  pDevPnpReq = NULL;
    DWORD                       dwBytesRet = 0;
    DWORD                       dwRet = ERROR_SUCCESS;
    ULONG                       p1394ApiReqLen = 0;

    if (!pVirtualDevice->DeviceID)
    {
        dwRet = ERROR_INVALID_PARAMETER;

        goto Exit_RemoveVirtualDriver;
    }

    _itoa_s (
        BusNumber, 
        (CHAR *) &BusName[11], 
        ((sizeof (BusName) / sizeof (BusName[0])) - (strlen((CHAR *)BusName))),
        10);


    hDevice = OpenDevice (hWnd, (PSTR) &BusName);
    if (hDevice != INVALID_HANDLE_VALUE) 
    {

        //taking care of NULL termination character
        retVal = strlen(pVirtualDevice->DeviceID) + 1;

        if (S_OK != (SizeTToULong (retVal, &ulStrLen)))
        {
            dwRet = GetLastError();
            TRACE (TL_ERROR, (hWnd, "SizeTToULong failed: %d\n", dwRet));

            goto Exit_RemoveVirtualDriver;
        }



        if ( pVirtualDevice->fulFlags & IEEE1394_REQUEST_FLAG_UNICODE ) 
        {
            p1394ApiReq = \
                (PIEEE1394_API_REQUEST) LocalAlloc (
                LPTR, 
                sizeof(IEEE1394_API_REQUEST)+(ulStrLen * sizeof(WCHAR)));

            if (NULL == p1394ApiReq)
            {
                dwRet = GetLastError();
                TRACE (TL_FATAL, (hWnd, "LocalAlloc failed: %d\n", dwRet));

                goto Exit_RemoveVirtualDriver;
            }

            p1394ApiReqLen = \
                sizeof(IEEE1394_API_REQUEST)+(ulStrLen * sizeof(WCHAR));
        } 
        else 
        {
            p1394ApiReq = (PIEEE1394_API_REQUEST) LocalAlloc (
                LPTR, 
                sizeof(IEEE1394_API_REQUEST)+ulStrLen);
            
            if (NULL == p1394ApiReq)
            {
                dwRet = GetLastError();
                TRACE (TL_FATAL, (hWnd, "LocalAlloc failed: %d\n", dwRet));

                goto Exit_RemoveVirtualDriver;
            }

            p1394ApiReqLen = sizeof(IEEE1394_API_REQUEST)+ ulStrLen;
        }

        p1394ApiReq->RequestNumber = IEEE1394_API_REMOVE_VIRTUAL_DEVICE;
        p1394ApiReq->Flags = 0;

        pDevPnpReq = &p1394ApiReq->u.RemoveVirtualDevice;

        pDevPnpReq->fulFlags = pVirtualDevice->fulFlags;
        pDevPnpReq->Reserved = 0;
        pDevPnpReq->InstanceId = pVirtualDevice->InstanceID;
        
        if (pVirtualDevice->fulFlags & IEEE1394_REQUEST_FLAG_UNICODE) 
        {
            if (S_OK != StringCchCopyNW (
                (LPWSTR)&pDevPnpReq->DeviceId,
                ulStrLen,
                (LPWSTR)pVirtualDevice->DeviceID, 
                ulStrLen))
            {
                TRACE (TL_FATAL, (hWnd, "StringCchCopyNW failed\n"));
                dwRet = ERROR_INSUFFICIENT_BUFFER;

                goto Exit_RemoveVirtualDriver;
            }
        
            if (!DeviceIoControl (
                hDevice,
                IOCTL_IEEE1394_API_REQUEST,
                p1394ApiReq,
                p1394ApiReqLen,
                NULL,
                0,
                &dwBytesRet,
                NULL))
            {
                dwRet = GetLastError();

                goto Exit_RemoveVirtualDriver;
            }
        } 
        else 
        {
            if (S_OK != StringCchCopyNA (
                (STRSAFE_LPSTR) &pDevPnpReq->DeviceId,
                ulStrLen,
                (STRSAFE_LPSTR) pVirtualDevice->DeviceID, 
                ulStrLen))
            {
                TRACE (TL_FATAL, (hWnd, "StringCchCopyNA failed\n"));
                dwRet = ERROR_INSUFFICIENT_BUFFER;

                goto Exit_RemoveVirtualDriver;
            }

            if (!DeviceIoControl (
                hDevice,
                IOCTL_IEEE1394_API_REQUEST,
                p1394ApiReq,
                p1394ApiReqLen,
                NULL,
                0,
                &dwBytesRet,
                NULL))
            {
                dwRet = GetLastError();
            }
        }
    }
    else 
    {
        dwRet = ERROR_INVALID_HANDLE;
    }

Exit_RemoveVirtualDriver:

    if (INVALID_HANDLE_VALUE != hDevice)
    {
        CloseHandle (hDevice);
    }

    if (p1394ApiReq)
    {
        LocalFree (p1394ApiReq);
    }

    return dwRet;
}
コード例 #8
0
ファイル: util.c プロジェクト: 340211173/Driver
DWORD
WINAPI
AddVirtualDriver (
                  HWND                hWnd,
                  PVIRT_DEVICE    pVirtualDevice,
                  ULONG               BusNumber)
{
    HANDLE                      hDevice;
    ULONG                       ulStrLen;
    size_t                      retVal = 0;
    UCHAR                       BusName[16] = "\\\\.\\1394BUS";
    PIEEE1394_API_REQUEST       p1394ApiReq;
    PIEEE1394_VDEV_PNP_REQUEST  pDevPnpReq;
    DWORD                       dwBytesRet;
    DWORD                       dwRet;
    ULONG                       p1394ApiReqLen = 0;

    TRACE(TL_TRACE, (hWnd, "AddVirtual Driver\r\n"));

    _itoa_s (
        BusNumber, 
        (CHAR *) &BusName[11], 
        ((sizeof (BusName) / sizeof (BusName[0])) - (strlen((CHAR *)BusName))),
        10);


    TRACE (TL_TRACE, (hWnd, "Bus: %s\r\n", BusName));

    hDevice = OpenDevice (hWnd, (PSTR) &BusName);
    if (hDevice != INVALID_HANDLE_VALUE)
    {

        //taking care of NULL terminating character
        retVal = strlen(pVirtualDevice->DeviceID) + 1;

        if (S_OK != (SizeTToULong (retVal, &ulStrLen)))
        {
            dwRet = GetLastError();
            TRACE (TL_ERROR, (hWnd, "SizeTToULong failed: %d\n", dwRet));
            return dwRet;
        }


        if ( pVirtualDevice->fulFlags & IEEE1394_REQUEST_FLAG_UNICODE ) 
        {
            p1394ApiReq = (PIEEE1394_API_REQUEST) LocalAlloc (
                LPTR, 
                sizeof(IEEE1394_API_REQUEST)+(ulStrLen * sizeof(WCHAR)));

            if (NULL == p1394ApiReq)
            {
                DWORD gle = GetLastError();

                TRACE (TL_FATAL, (hWnd, "LocalAlloc failed: %d\n", gle));
                return gle;
            }

            p1394ApiReqLen = \
                sizeof(IEEE1394_API_REQUEST)+(ulStrLen * sizeof(WCHAR));
        } 
        else 
        {
            p1394ApiReq = (PIEEE1394_API_REQUEST) LocalAlloc(LPTR, 
                sizeof(IEEE1394_API_REQUEST)+ulStrLen);

            if (NULL == p1394ApiReq)
            {
                DWORD gle = GetLastError();

                TRACE (TL_FATAL, (hWnd, "LocalAlloc failed: %d\n", gle));
                return gle;
            }

            p1394ApiReqLen = sizeof(IEEE1394_API_REQUEST)+ ulStrLen;
        }

        p1394ApiReq->RequestNumber = IEEE1394_API_ADD_VIRTUAL_DEVICE;
        p1394ApiReq->Flags = pVirtualDevice->fulFlags;

        pDevPnpReq = &p1394ApiReq->u.AddVirtualDevice;

        pDevPnpReq->fulFlags = pVirtualDevice->fulFlags;
        pDevPnpReq->Reserved = 0;
        pDevPnpReq->InstanceId = pVirtualDevice->InstanceID;

        if ( pVirtualDevice->fulFlags & IEEE1394_REQUEST_FLAG_UNICODE ) 
        {
            if (S_OK != StringCchCopyNW (
                (LPWSTR)&pDevPnpReq->DeviceId,
                ulStrLen,
                (LPWSTR)pVirtualDevice->DeviceID, 
                ulStrLen))
                            
            {
                TRACE (TL_FATAL, (hWnd, "StringCchCopyNW failed\n"));
                return ERROR_INSUFFICIENT_BUFFER;
            }


            dwRet = DeviceIoControl (
                hDevice,
                IOCTL_IEEE1394_API_REQUEST,
                p1394ApiReq,
                p1394ApiReqLen,
                NULL,
                0,
                &dwBytesRet,
                NULL);
        } 
        else 
        {
            if (S_OK != StringCchCopyNA (
                (STRSAFE_LPSTR) &pDevPnpReq->DeviceId,
                ulStrLen,
                (STRSAFE_LPSTR) pVirtualDevice->DeviceID, 
                ulStrLen))
            {
                TRACE (TL_FATAL, (hWnd, "StringCchCopyNA failed\n"));
                return ERROR_INSUFFICIENT_BUFFER;
            }

            dwRet = DeviceIoControl (
                hDevice,
                IOCTL_IEEE1394_API_REQUEST,
                p1394ApiReq,
                p1394ApiReqLen,
                NULL,
                0,
                &dwBytesRet,
                NULL);
        }

        if (!dwRet)
        {
            
            dwRet = GetLastError();
            TRACE(
                TL_WARNING, 
                (hWnd, 
                "Failed IOCTL_IEEE1394_API_REQEST 0x%x\r\n", 
                dwRet));
        }
        else 
        {
            TRACE(TL_WARNING, (hWnd, "Succeeded IOCTL_IEEE1394_API_REQEST\r\n"));
            dwRet = ERROR_SUCCESS;
        }

        // free resources

        CloseHandle (hDevice);
        LocalFree(p1394ApiReq);
    }
    else 
    {
        dwRet = ERROR_INVALID_HANDLE;
    }

    return dwRet;
}
コード例 #9
0
ファイル: strsafe_copy.c プロジェクト: JSund/libstrsafe
HRESULT StringCchCopyW(
        LPWSTR pszDest,
        size_t cchDest,
        LPCWSTR pszSrc){
    return StringCchCopyNW(pszDest, cchDest, pszSrc, cchDest);
}
コード例 #10
0
ファイル: environment.c プロジェクト: Moteesh/reactos
BOOL
WINAPI
CreateEnvironmentBlock(OUT LPVOID *lpEnvironment,
                       IN HANDLE hToken,
                       IN BOOL bInherit)
{
    NTSTATUS Status;
    LONG lError;
    PWSTR* Environment = (PWSTR*)lpEnvironment;
    DWORD Length;
    DWORD dwType;
    HKEY hKey;
    HKEY hKeyUser;
    LPWSTR lpUserName = NULL;
    LPWSTR lpDomainName = NULL;
    WCHAR Buffer[MAX_PATH];
    WCHAR szValue[1024];

    DPRINT("CreateEnvironmentBlock() called\n");

    if (lpEnvironment == NULL)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }

    Status = RtlCreateEnvironment((BOOLEAN)bInherit, Environment);
    if (!NT_SUCCESS(Status))
    {
        DPRINT1("RtlCreateEnvironment() failed (Status %lx)\n", Status);
        SetLastError(RtlNtStatusToDosError(Status));
        return FALSE;
    }

    /* Set 'SystemRoot' variable */
    Length = ARRAYSIZE(Buffer);
    if (GetEnvironmentVariableW(L"SystemRoot", Buffer, Length))
    {
        SetUserEnvironmentVariable(Environment,
                                   L"SystemRoot",
                                   Buffer,
                                   FALSE);
    }

    /* Set 'SystemDrive' variable */
    if (GetEnvironmentVariableW(L"SystemDrive", Buffer, Length))
    {
        SetUserEnvironmentVariable(Environment,
                                   L"SystemDrive",
                                   Buffer,
                                   FALSE);
    }

    /* Set variables from Session Manager */
    if (!SetSystemEnvironment(Environment))
    {
        RtlDestroyEnvironment(*Environment);
        return FALSE;
    }

    /* Set 'COMPUTERNAME' variable */
    Length = ARRAYSIZE(Buffer);
    if (GetComputerNameW(Buffer, &Length))
    {
        SetUserEnvironmentVariable(Environment,
                                   L"COMPUTERNAME",
                                   Buffer,
                                   FALSE);
    }

    /* Set 'ALLUSERSPROFILE' variable */
    Length = ARRAYSIZE(Buffer);
    if (GetAllUsersProfileDirectoryW(Buffer, &Length))
    {
        SetUserEnvironmentVariable(Environment,
                                   L"ALLUSERSPROFILE",
                                   Buffer,
                                   FALSE);
    }

    /* Set 'USERPROFILE' variable to the default users profile */
    Length = ARRAYSIZE(Buffer);
    if (GetDefaultUserProfileDirectoryW(Buffer, &Length))
    {
        SetUserEnvironmentVariable(Environment,
                                   L"USERPROFILE",
                                   Buffer,
                                   TRUE);
    }

    lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
                           L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion",
                           0,
                           KEY_READ,
                           &hKey);
    if (lError == ERROR_SUCCESS)
    {
        Length = sizeof(szValue);
        lError = RegQueryValueExW(hKey,
                                  L"ProgramFilesDir",
                                  NULL,
                                  &dwType,
                                  (LPBYTE)szValue,
                                  &Length);
        if (lError == ERROR_SUCCESS)
        {
            SetUserEnvironmentVariable(Environment,
                                       L"ProgramFiles",
                                       szValue,
                                       FALSE);
        }

        Length = sizeof(szValue);
        lError = RegQueryValueExW(hKey,
                                  L"CommonFilesDir",
                                  NULL,
                                  &dwType,
                                  (LPBYTE)szValue,
                                  &Length);
        if (lError == ERROR_SUCCESS)
        {
            SetUserEnvironmentVariable(Environment,
                                       L"CommonProgramFiles",
                                       szValue,
                                       FALSE);
        }

        RegCloseKey(hKey);
    }

    /*
     * If no user token is specified, the system environment variables are set
     * and we stop here, otherwise continue setting the user-specific variables.
     */
    if (hToken == NULL)
        return TRUE;

    hKeyUser = GetCurrentUserKey(hToken);
    if (hKeyUser == NULL)
    {
        DPRINT1("GetCurrentUserKey() failed\n");
        RtlDestroyEnvironment(*Environment);
        return FALSE;
    }

    /* Set 'USERPROFILE' variable */
    Length = ARRAYSIZE(Buffer);
    if (GetUserProfileDirectoryW(hToken, Buffer, &Length))
    {
        DWORD MinLen = 2;

        SetUserEnvironmentVariable(Environment,
                                   L"USERPROFILE",
                                   Buffer,
                                   FALSE);

        // FIXME: Strangely enough the following two environment variables
        // are not set by userenv.dll in Windows... See r68284 / CORE-9875
        // FIXME2: This is done by msgina.dll !!

        /* At least <drive letter>:<path> */
        if (Length > MinLen)
        {
            /* Set 'HOMEDRIVE' variable */
            StringCchCopyNW(szValue, ARRAYSIZE(Buffer), Buffer, MinLen);
            SetUserEnvironmentVariable(Environment,
                                       L"HOMEDRIVE",
                                       szValue,
                                       FALSE);

            /* Set 'HOMEPATH' variable */
            StringCchCopyNW(szValue, ARRAYSIZE(Buffer), Buffer + MinLen, Length - MinLen);
            SetUserEnvironmentVariable(Environment,
                                       L"HOMEPATH",
                                       szValue,
                                       FALSE);
        }
    }
    else
    {
        DPRINT1("GetUserProfileDirectoryW failed with error %lu\n", GetLastError());
    }

    if (GetUserAndDomainName(hToken,
                             &lpUserName,
                             &lpDomainName))
    {
        /* Set 'USERNAME' variable */
        SetUserEnvironmentVariable(Environment,
                                   L"USERNAME",
                                   lpUserName,
                                   FALSE);

        /* Set 'USERDOMAIN' variable */
        SetUserEnvironmentVariable(Environment,
                                   L"USERDOMAIN",
                                   lpDomainName,
                                   FALSE);

        if (lpUserName != NULL)
            LocalFree(lpUserName);

        if (lpDomainName != NULL)
            LocalFree(lpDomainName);
    }

    /* Set user environment variables */
    SetUserEnvironment(Environment,
                       hKeyUser,
                       L"Environment");

    /* Set user volatile environment variables */
    SetUserEnvironment(Environment,
                       hKeyUser,
                       L"Volatile Environment");

    RegCloseKey(hKeyUser);

    return TRUE;
}
コード例 #11
0
ファイル: BatStat.c プロジェクト: ied206/BatteryLine
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;
}