Kaynağa Gözat

T20M5021 #comment 开始实现对.ini类型文件的读取

gifur 5 yıl önce
ebeveyn
işleme
69c2fecb2b

+ 4 - 0
libtoolkit/__vcscan.c

@@ -5,6 +5,10 @@
     Function to scan a string like scanf().
 */
 
+/*
+ * Description: implement function __vcscan which defined at vsscanf.c
+ */
+
 
 #include "precompile.h"
 #define __vcscan __vcscan

+ 1 - 0
libtoolkit/iobuffer.c

@@ -3,6 +3,7 @@
 #include "refcnt.h"
 #include "memutil.h"
 #include "list.h"
+#include <assert.h>
 
 struct iobuffer_t
 {

+ 1 - 0
libtoolkit/refcnt.h

@@ -3,6 +3,7 @@
 
 #pragma once
 #include <winpr/wtypes.h>
+#include <winpr/interlocked.h> /*for warning: implicit declaration of function InterlockedIncrement*/
 
 #ifdef __cplusplus
 extern "C" {

+ 7 - 0
libtoolkit/test/test_iniutil.cpp

@@ -0,0 +1,7 @@
+#include "iniutil.h"
+#include <gtest/gtest.h>
+
+TEST(LibToolkitTest, INIFileLoadTest)
+{
+	
+}

+ 2 - 2
libtoolkit/vsscanf.c

@@ -48,7 +48,7 @@ int __vcscan (
 
 
 
-#if _MSC_VER < 1900
+#if defined(_MSC_VER) && _MSC_VER < 1900
 
 TOOLKIT_API 	int vsscanf (
 
@@ -95,4 +95,4 @@ TOOLKIT_API 	int vsscanf (
     return rc;
 } /* vsscanf */
 
-#endif
+#endif //defined(_MSC_VER) && _MSC_VER < 1900

+ 4 - 2
libtoolkit/vsscanf.h

@@ -3,7 +3,9 @@
 
 #pragma once
 
-
+/*
+ * vsscanf1 is invoked at iniutil.c
+ */
 
 #include "config.h"
 
@@ -12,7 +14,7 @@ extern "C" {
 #endif
 
 #include <stdarg.h>
-#if _MSC_VER < 1900
+#if defined(_MSC_VER) && _MSC_VER < 1900
 	TOOLKIT_API int vsscanf(const char* buffer, const char* format, va_list     argPtr);
 #endif
 	TOOLKIT_API int vsscanf1(const char* str, const char* format, va_list arg);

+ 45 - 0
winpr/include/winpr/ini.h

@@ -51,6 +51,51 @@ extern "C"
 	WINPR_API wIniFile* IniFile_New(void);
 	WINPR_API void IniFile_Free(wIniFile* ini);
 
+WINPR_API DWORD GetPrivateProfileStringA(LPCSTR lpAppName, LPCSTR lpKeyName, LPCSTR lpDefault,
+		LPSTR lpReturnedString, DWORD nSize, LPCSTR lpFileName);
+
+WINPR_API DWORD GetPrivateProfileStringW(LPCWSTR lpAppName, LPCWSTR lpKeyName, LPCWSTR lpDefault,
+		LPWSTR lpReturnedString, DWORD nSize, LPCWSTR lpFileName);
+
+#ifdef UNICODE
+#define GetPrivateProfileString  GetPrivateProfileStringW
+#else
+#define GetPrivateProfileString  GetPrivateProfileStringA
+#endif // !UNICODE
+
+WINPR_API UINT GetPrivateProfileIntA(LPCSTR lpAppName, LPCSTR lpKeyName, INT nDefault, LPCSTR lpFileName);
+WINPR_API UINT GetPrivateProfileIntW(LPCWSTR lpAppName, LPCWSTR lpKeyName, INT nDefault, LPCWSTR lpFileName);
+#ifdef UNICODE
+#define GetPrivateProfileInt  GetPrivateProfileIntW
+#else
+#define GetPrivateProfileInt  GetPrivateProfileIntA
+#endif // !UNICODE
+
+WINPR_API DWORD GetPrivateProfileSectionNamesA(LPSTR lpszReturnBuffer, DWORD nSize, LPCSTR lpFileName);
+WINPR_API DWORD GetPrivateProfileSectionNamesW(LPWSTR lpszReturnBuffer, DWORD nSize, LPCWSTR lpFileName);
+#ifdef UNICODE
+#define GetPrivateProfileSectionNames  GetPrivateProfileSectionNamesW
+#else
+#define GetPrivateProfileSectionNames  GetPrivateProfileSectionNamesA
+#endif // !UNICODE
+
+WINPR_API BOOL WritePrivateProfileStringA(LPCSTR lpAppName, LPCSTR lpKeyName, LPCSTR lpString, LPCSTR lpFileName);
+WINPR_API BOOL WritePrivateProfileStringW(LPCWSTR lpAppName, LPCWSTR lpKeyName, LPCWSTR lpString, LPCWSTR lpFileName);
+#ifdef UNICODE
+#define WritePrivateProfileString  WritePrivateProfileStringW
+#else
+#define WritePrivateProfileString  WritePrivateProfileStringA
+#endif // !UNICODE
+
+WINPR_API BOOL WritePrivateProfileSectionA(LPCSTR lpAppName, LPCSTR lpString, LPCSTR lpFileName);
+WINPR_API BOOL WritePrivateProfileSectionW(LPCWSTR lpAppName, LPCWSTR lpString,LPCWSTR lpFileName);
+#ifdef UNICODE
+#define WritePrivateProfileSection  WritePrivateProfileSectionW
+#else
+#define WritePrivateProfileSection  WritePrivateProfileSectionA
+#endif // !UNICODE
+
+
 #ifdef __cplusplus
 }
 #endif

+ 1 - 0
winpr/libwinpr/interlocked/test/TestInterlockedAccess.c

@@ -15,6 +15,7 @@ int TestInterlockedAccess(int argc, char* argv[])
 
 	/* InterlockedIncrement */
 
+	/*allocates memory on a specified alignment boundary*/
 	Addend = _aligned_malloc(sizeof(LONG), sizeof(LONG));
 	if (!Addend)
 	{

+ 273 - 8
winpr/libwinpr/utils/ini.c

@@ -24,17 +24,21 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
 #include <errno.h>
 #include <winpr/wtypes.h>
 #include <winpr/crt.h>
 
 #include <winpr/ini.h>
+#include "../log.h"
+#define TAG WINPR_TAG("ini")
 
 struct _wIniFileKey
 {
 	char* name;
 	char* value;
+	BOOL invalid; /*extend */
 };
 typedef struct _wIniFileKey wIniFileKey;
 
@@ -44,6 +48,7 @@ struct _wIniFileSection
 	size_t nKeys;
 	size_t cKeys;
 	wIniFileKey** keys;
+	BOOL invalid; /*extend */
 };
 typedef struct _wIniFileSection wIniFileSection;
 
@@ -65,6 +70,9 @@ struct _wIniFile
 static BOOL IniFile_Load_NextLine(wIniFile* ini, char* str)
 {
 	size_t length = 0;
+
+still: // fix \r\n  gifur
+
 	ini->nextLine = strtok_s(str, "\n", &ini->tokctx);
 
 	if (ini->nextLine)
@@ -78,8 +86,13 @@ static BOOL IniFile_Load_NextLine(wIniFile* ini, char* str)
 			length--;
 		}
 
-		if (length < 1)
-			ini->nextLine = NULL;
+		if (length < 1) {  // must be zero !!
+			if(strlen(ini->tokctx) > 0) {
+				goto still;
+			}else {
+				ini->nextLine = NULL;
+			}
+		}
 	}
 
 	return (ini->nextLine) ? TRUE : FALSE;
@@ -111,6 +124,7 @@ static BOOL IniFile_Load_String(wIniFile* ini, const char* iniString)
 	return TRUE;
 }
 
+/*fopen*/
 static BOOL IniFile_Open_File(wIniFile* ini, const char* filename)
 {
 	if (!ini || !filename)
@@ -127,6 +141,7 @@ static BOOL IniFile_Open_File(wIniFile* ini, const char* filename)
 	return TRUE;
 }
 
+/**/
 static BOOL IniFile_Load_File(wIniFile* ini, const char* filename)
 {
 	INT64 fileSize;
@@ -219,6 +234,7 @@ static wIniFileKey* IniFile_Key_New(const char* name, const char* value)
 	{
 		key->name = _strdup(name);
 		key->value = _strdup(value);
+		key->invalid = TRUE;
 
 		if (!key->name || !key->value)
 		{
@@ -255,6 +271,7 @@ static wIniFileSection* IniFile_Section_New(const char* name)
 		return NULL;
 
 	section->name = _strdup(name);
+	section->invalid = TRUE;
 
 	if (!section->name)
 	{
@@ -304,7 +321,8 @@ static wIniFileSection* IniFile_GetSection(wIniFile* ini, const char* name)
 
 	for (index = 0; index < ini->nSections; index++)
 	{
-		if (_stricmp(name, ini->sections[index]->name) == 0)
+		if (_stricmp(name, ini->sections[index]->name) == 0 
+			&& !!ini->sections[index]->invalid)
 		{
 			section = ini->sections[index];
 			break;
@@ -330,8 +348,7 @@ static wIniFileSection* IniFile_AddSection(wIniFile* ini, const char* name)
 			size_t new_size;
 			wIniFileSection** new_sect;
 			new_size = ini->cSections * 2;
-			new_sect =
-			    (wIniFileSection**)realloc(ini->sections, sizeof(wIniFileSection*) * new_size);
+			new_sect = (wIniFileSection**)realloc(ini->sections, sizeof(wIniFileSection*) * new_size);
 
 			if (!new_sect)
 				return NULL;
@@ -714,7 +731,7 @@ char* IniFile_WriteBuffer(wIniFile* ini)
 
 	if (!ini)
 		return NULL;
-
+	/*calculate the rquired buffer size for storing*/
 	for (i = 0; i < ini->nSections; i++)
 	{
 		section = ini->sections[i];
@@ -728,7 +745,7 @@ char* IniFile_WriteBuffer(wIniFile* ini)
 
 		size += 1;
 	}
-
+	/*allocate buffer*/
 	size += 1;
 	buffer = malloc(size + 1);
 
@@ -736,7 +753,7 @@ char* IniFile_WriteBuffer(wIniFile* ini)
 		return NULL;
 
 	offset = 0;
-
+	/*write to the buffer*/
 	for (i = 0; i < ini->nSections; i++)
 	{
 		section = ini->sections[i];
@@ -769,6 +786,7 @@ int IniFile_WriteFile(wIniFile* ini, const char* filename)
 		return -1;
 
 	length = strlen(buffer);
+	/*set write flag*/
 	ini->readOnly = FALSE;
 
 	if (!filename)
@@ -823,3 +841,250 @@ void IniFile_Free(wIniFile* ini)
 	free(ini->sections);
 	free(ini);
 }
+
+DWORD GetPrivateProfileStringA(LPCSTR lpAppName, LPCSTR lpKeyName, LPCSTR lpDefault,
+							   LPSTR lpReturnedString, DWORD nSize, LPCSTR lpFileName)
+{
+	wIniFile* ini;
+	DWORD nRetSize = 0;
+	const char* value;
+	wIniFileSection* pSection = NULL;
+	int index;
+	wIniFileKey* key = NULL;
+	char *t;
+	size_t totalLen = 0;
+	ini = IniFile_New();
+	if(IniFile_ReadFile(ini, lpFileName) < 0) {
+		IniFile_Free(ini);
+		WLog_ERR(TAG, "failed to parse %s", lpFileName);
+		return 0;
+	}
+	if(lpKeyName != NULL) {
+		value = IniFile_GetKeyValueString(ini, lpAppName, lpKeyName);
+		if(value) {
+			nRetSize = strlen(value);
+			if(nSize > 0 && lpReturnedString) {
+				strncpy(lpReturnedString, value, nSize > strlen(value)+1 ? strlen(value)+1 : nSize);
+			}
+		}
+	} else { // key == null
+
+		pSection = IniFile_GetSection(ini, lpAppName);
+		if (pSection) {
+			totalLen = 0;
+			for (index = 0; index < pSection->nKeys; index++) {
+				key = pSection->keys[index];
+				if(strlen(key->name) > 0)
+					totalLen += strlen(key->name) + 1;
+			}
+			totalLen++;
+//            if(totalLen > 0) {
+//                totalLen--;
+//            }
+			nRetSize = totalLen;
+			if(totalLen > 1 && nSize >= 2 && lpReturnedString) {
+
+				if(totalLen > nSize) {
+					// for compatible the upper invoke
+					nRetSize = nSize - 2;
+				} else {
+					char* temp = malloc(sizeof(char)*totalLen);
+					if(temp) {
+						memset(temp, 0, sizeof(char)*totalLen);
+						t = temp;
+						for (index = 0; index < pSection->nKeys; index++) {
+							key = pSection->keys[index];
+							if(strcmp(key->name, "InitiativeTransfer") == 0) {
+								;
+							}
+							if(strlen(key->name) > 0) {
+								strcpy(t, key->name);
+								t += strlen(key->name);
+								*t = '\0';
+								t++;
+							}
+						}
+						*t = '\0';
+						totalLen = nSize > totalLen ? totalLen : nSize;
+						memcpy(lpReturnedString, temp, sizeof(char)*totalLen);
+						free(temp);
+					}
+				}
+			}
+		}
+	}
+
+	if(nRetSize == 0 && nSize > 0 && lpReturnedString) {
+		lpReturnedString[0] = '\0';
+		if(lpDefault) {
+			nRetSize = nSize > strlen(lpDefault)+1 ? strlen(lpDefault)+1 : nSize;
+			strncpy(lpReturnedString, lpDefault, nRetSize);
+		}
+	}
+	IniFile_Free(ini);
+	return nRetSize;
+}
+
+DWORD GetPrivateProfileStringW(LPCWSTR lpAppName, LPCWSTR lpKeyName, LPCWSTR lpDefault,
+							   LPWSTR lpReturnedString, DWORD nSize, LPCWSTR lpFileName)
+{
+	WLog_ERR(TAG, "%s operation not implemented", __FUNCTION__);
+	return FALSE;
+}
+
+UINT GetPrivateProfileIntA(LPCSTR lpAppName, LPCSTR lpKeyName, INT nDefault, LPCSTR lpFileName)
+{
+	UINT ret = nDefault;
+	wIniFile* ini;
+	ini = IniFile_New();
+	if(!ini) {
+		return ret;
+	}
+	if(IniFile_ReadFile(ini, lpFileName) < 0) {
+		IniFile_Free(ini);
+		WLog_ERR(TAG, "failed to parse %s", lpFileName);
+		return ret;
+	}
+	ret = IniFile_GetKeyValueInt(ini, lpAppName, lpKeyName);
+	IniFile_Free(ini);
+	return ret;
+}
+
+UINT GetPrivateProfileIntW(LPCWSTR lpAppName, LPCWSTR lpKeyName, INT nDefault, LPCWSTR lpFileName)
+{
+	WLog_ERR(TAG, "%s operation not implemented", __FUNCTION__);
+	return FALSE;
+}
+
+DWORD GetPrivateProfileSectionNamesA(LPSTR lpszReturnBuffer, DWORD nSize, LPCSTR lpFileName)
+{
+	DWORD ret = 0;
+	wIniFile* ini;
+	int index;
+	int length;
+	int validCount = 0;
+	int nameLength;
+	char* sectionNames;
+	wIniFileSection* section = NULL;
+	char *p;
+	ini = IniFile_New();
+	if(!ini) {
+		return ret;
+	}
+	if(IniFile_ReadFile(ini, lpFileName) < 0) {
+		IniFile_Free(ini);
+		WLog_ERR(TAG, "failed to parse %s", lpFileName);
+		return ret;
+	}
+	length = 0;
+	for (index = 0; index < ini->nSections; index++) {
+		section = ini->sections[index];
+		if(section->invalid) {
+			continue;
+		}
+		validCount++;
+		nameLength = (int) strlen(section->name);
+		length += (nameLength + 1);
+	}
+	length++;
+
+	sectionNames = (char*)malloc(length);
+	if (!sectionNames)
+		return ret;
+	p = sectionNames;
+	for (index = 0; index < ini->nSections; index++)
+	{
+		section = ini->sections[index];
+		if(section->invalid) {
+			continue;
+		}
+		nameLength = (int) strlen(section->name);
+		CopyMemory(p, section->name, nameLength + 1);
+		p += (nameLength + 1);
+	}
+	*p = '\0';
+
+	ret = length;
+	if(lpszReturnBuffer != NULL && nSize > 0) {
+		if(nSize < length) {
+			ret = nSize - 2;
+		} else {
+			CopyMemory(lpszReturnBuffer, sectionNames, length);
+		}
+	}
+	if(sectionNames != NULL) {
+		free(sectionNames);
+	}
+	IniFile_Free(ini);
+	return ret;
+}
+
+DWORD GetPrivateProfileSectionNamesW(LPWSTR lpszReturnBuffer, DWORD nSize, LPCWSTR lpFileName)
+{
+	WLog_ERR(TAG, "%s operation not implemented", __FUNCTION__);
+	return FALSE;
+}
+
+BOOL WritePrivateProfileStringA(LPCSTR lpAppName, LPCSTR lpKeyName, LPCSTR lpString, LPCSTR lpFileName)
+{
+	wIniFile* ini;
+	BOOL ret = TRUE;
+	ini = IniFile_New();
+	if(!ini) {
+		return FALSE;
+	}
+	if(IniFile_ReadFile(ini, lpFileName) < 0 && access(lpFileName, F_OK) == 0) {
+		ret = FALSE;
+	} else {
+		if(IniFile_SetKeyValueString(ini, lpAppName, lpKeyName, lpString) < 0) {
+			ret = FALSE;
+		} else {
+			if(IniFile_WriteFile(ini, lpFileName) < 0) {
+				ret = FALSE;
+			}
+		}
+	}
+	IniFile_Free(ini);
+	return ret;
+}
+
+BOOL WritePrivateProfileStringW(LPCWSTR lpAppName, LPCWSTR lpKeyName, LPCWSTR lpString, LPCWSTR lpFileName)
+{
+	WLog_ERR(TAG, "%s operation not implemented", __FUNCTION__);
+	return FALSE;
+}
+
+BOOL WritePrivateProfileSectionA(LPCSTR lpAppName, LPCSTR lpString, LPCSTR lpFileName)
+{
+	wIniFile* ini;
+	BOOL ret = TRUE;
+	wIniFileSection* pSection = NULL;
+	ini = IniFile_New();
+	if(!ini) {
+		return FALSE;
+	}
+	if(IniFile_ReadFile(ini, lpFileName) < 0) {
+		ret = FALSE;
+	} else {
+		if(lpString == NULL) {
+			//to delete the section...
+			pSection = IniFile_GetSection(ini, lpAppName);
+			if(!pSection) {
+				ret = FALSE;
+			} else {
+				pSection->invalid = TRUE;
+			}
+		}
+	}
+	if(ret == TRUE && IniFile_WriteFile(ini, lpFileName) < 0) {
+		ret = FALSE;
+	}
+	IniFile_Free(ini);
+	return ret;
+}
+
+WINPR_API BOOL WritePrivateProfileSectionW(LPCWSTR lpAppName, LPCWSTR lpString,LPCWSTR lpFileName)
+{
+	WLog_ERR(TAG, "%s operation not implemented", __FUNCTION__);
+	return FALSE;
+}

+ 20 - 0
winpr/libwinpr/utils/test/CMakeLists.txt

@@ -39,6 +39,26 @@ target_link_libraries(${MODULE_NAME} winpr)
 
 set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
 
+if(NOT MSVC)
+	set(TEST_DIR "${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME}Area")
+	set(LINE_FEED "\n")
+else()
+	set(TEST_DIR "${TESTING_OUTPUT_DIRECTORY}/${CMAKE_BUILD_TYPE}/${MODULE_NAME}Area")
+	set(LINE_FEED "\r\n")
+endif()
+file(MAKE_DIRECTORY "${TEST_DIR}")
+file(WRITE "${TEST_DIR}/ini_test.ini" 
+	"[Section1]${LINE_FEED}"
+	"KeyString1=Value1${LINE_FEED}"
+	"KeyInt1=1${LINE_FEED}"
+	"[Section2]${LINE_FEED}"
+	"KeyString2=Value1${LINE_FEED}"
+	"KeyInt2=2${LINE_FEED}"
+	"[Section3]${LINE_FEED}"
+	"KeyString3=Value3${LINE_FEED}"
+	"KeyInt3=3456${LINE_FEED}"
+	"KeyHex3=0x24964611${LINE_FEED}")
+
 foreach(test ${${MODULE_PREFIX}_TESTS})
 	get_filename_component(TestName ${test} NAME_WE)
 	add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName})

+ 22 - 1
winpr/libwinpr/utils/test/TestIni.c

@@ -36,6 +36,25 @@ const char TEST_INI_03[] = "[FreeRDS]\n"
                            "sysconfdir=\"etc\"\n"
                            "\n";
 
+int TestWinPrivateProfile()
+{
+	UINT n;
+	char buf[240] = { 0 };
+	const char* iniFileName = "./TestWinPRUtils/ini_test.ini";
+	n = GetPrivateProfileIntA("Section1", "KeyInt1", 0, iniFileName);
+	if(n != 1)
+	{
+		printf("get [Section1]'s KeyInt1 is not the dream one, return value: %d\n", n);
+		return -1;
+	}
+	n = GetPrivateProfileIntA("Section1", "KeyInt2", 4, iniFileName);
+	if (n != 4) {
+		printf("get [Section1]'s KeyInt2 should be returned default one, return value: %d\n", n);
+		return -1;
+	}
+	return 0;
+}
+
 int TestIni(int argc, char* argv[])
 {
 	int i, j;
@@ -138,5 +157,7 @@ int TestIni(int argc, char* argv[])
 	}
 
 	IniFile_Free(ini);
-	return 0;
+
+	return TestWinPrivateProfile();
+	//return 0;
 }