/** * Fills <code>MidpString</code> arrays for locales and action_maps from * <code>ActionMap</code> objects. * <BR>Length of <code>actionnames</code> array must be the same as in * <code>act_num</code> parameter for each element of <code>ActionMap</code> * array. * * @param o <code>ActionMap[]</code> object * @param handler pointer on <code>JSR211_content_handler</code> structure * being filled up * @return KNI_OK - if successfully get all fields, * KNI_ERR or KNI_ENOMEM - otherwise */ static int fillActionMap(jobject o, JSR211_content_handler* handler) { int ret = KNI_OK; // returned result int len; // number of locales len = KNI_IsNullHandle(o)? 0: (int)KNI_GetArrayLength(o); if (len > 0) { int i, j; int n = handler->act_num; // number of actions pcsl_string *locs = NULL; // fetched locales pcsl_string *nams = NULL; // fetched action names KNI_StartHandles(3); KNI_DeclareHandle(map); // current ANMap object KNI_DeclareHandle(str); // the ANMap's locale|name String object KNI_DeclareHandle(arr); // the ANMap's array of names object do { // allocate buffers handler->locales = alloc_pcsl_string_list(len); if (handler->locales == NULL) { ret = KNI_ENOMEM; break; } handler->locale_num = len; handler->action_map = alloc_pcsl_string_list(len * n); if (handler->action_map == NULL) { ret = KNI_ENOMEM; break; } // iterate array elements locs = handler->locales; nams = handler->action_map; for (i = 0; i < len && ret == KNI_OK; i++) { KNI_GetObjectArrayElement(o, i, map); KNI_GetObjectField(map, anMapLocale, str); if (PCSL_STRING_OK != midp_jstring_to_pcsl_string(str, locs++)) { ret = KNI_ENOMEM; break; } KNI_GetObjectField(map, anMapActionnames, arr); for (j = 0; j < n; j++) { KNI_GetObjectArrayElement(arr, j, str); if (PCSL_STRING_OK != midp_jstring_to_pcsl_string(str, nams++)) { ret = KNI_ENOMEM; break; } } } } while (0); KNI_EndHandles(); } return ret; }
/** * Deserializes string array [arr] from the char buffer [ptr]. * The array is limited by '\n' or by terminated zero. * Each string entry delimited by a whitespace ' '. * After deserialization ptr is moved at start of the next line. * @return 0 if failed. */ static int fillArray(char **ptr, /*OUT*/int* len, /*OUT*/pcsl_string** arr) { char *p0, *p1; pcsl_string* str; int n = 1; p1 = p0 = *ptr; while (*p1 != 0 && *p1 != '\n') { if (*p1 == ' ') n++; p1++; } *ptr = (*p1 == 0? p1: p1 + 1); if ((p1 - p0) > 0) { str = alloc_pcsl_string_list(n); if (str == NULL) { return 0; } *arr = str; *len = n; while (n--) { p1 = p0; while (*p1 != ' ' && *p1 != 0 && *p1 != '\n') p1++; if (PCSL_STRING_OK != pcsl_string_convert_from_utf8((jbyte*)p0, p1 - p0, str)) return 0; p0 = p1 + 1; str++; } } return 1; }
/** * Fetch a KNI String array object into the string array. * * @param arrObj KNI Java String object handle * @param arrPtr the String array pointer for values storing * @return number of retrieved strings * <BR>KNI_ENOMEM - indicates memory allocation error */ static int getStringArray(jobjectArray arrObj, pcsl_string** arrPtr) { int i, n = 0; pcsl_string* arr; KNI_StartHandles(1); KNI_DeclareHandle(strObj); n = KNI_IsNullHandle(arrObj)? 0: (int)KNI_GetArrayLength(arrObj); while (n > 0) { arr = alloc_pcsl_string_list(n); if (arr == NULL) { n = KNI_ENOMEM; break; } *arrPtr = arr; for (i = 0; i < n; i++, arr++) { KNI_GetObjectArrayElement(arrObj, i, strObj); if (PCSL_STRING_OK != midp_jstring_to_pcsl_string(strObj, arr)) { free_pcsl_string_list(*arrPtr, n); *arrPtr = NULL; n = KNI_ENOMEM; break; } } break; } KNI_EndHandles(); return n; }
/** * Reads string array from the file. * * @param array_size pointer to result array length * @param strings pointer to result array * @return number of bytes read */ static int read_string_array(int* array_size, pcsl_string** strings) { int array_len; int bytes_read; pcsl_string* current_string; storageRead(&io_error_message, table_file, (char *)&array_len, sizeof(int)); storageRead(&io_error_message, table_file, (char *)array_size, sizeof(int)); bytes_read = sizeof(int) * 2; if (*array_size > 0) { *strings = alloc_pcsl_string_list(*array_size); for (current_string = *strings; bytes_read < array_len; current_string++) { bytes_read += read_string(current_string); } } else { *array_size = 0; } return bytes_read; }
/** * Loads the properties of a MIDlet suite from persistent storage. * * @param suiteId ID of the suite * @param pJadProps [out] pointer to a structure containing an array of strings, * in a pair pattern of key and value; NULL may be passed if it is not required * to read JAD properties * @param pJarProps [out] pointer to a structure containing an array of strings, * in a pair pattern of key and value; NULL may be passed if it is not required * to read JAR properties * * @return error code (ALL_OK for success) */ MIDPError load_install_properties(SuiteIdType suiteId, MidpProperties* pJadProps, MidpProperties* pJarProps) { pcsl_string filename; char* pszError = NULL; int handle, i, n; int numberOfProps; MIDPError status; status = get_property_file(suiteId, KNI_TRUE, &filename); if (status != ALL_OK) { return status; } handle = storage_open(&pszError, &filename, OPEN_READ); pcsl_string_free(&filename); if (pszError != NULL) { storageFreeError(pszError); return IO_ERROR; } status = ALL_OK; /* Read JAD, then JAR properties. */ for (n = 0; n < 2; n++) { MidpProperties *pProps = n ? pJarProps : pJadProps; if (!pProps) { continue; } storageRead(&pszError, handle, (char*)&numberOfProps, sizeof (numberOfProps)); if (pszError != NULL) { break; } pProps->pStringArr = alloc_pcsl_string_list(numberOfProps << 1); for (i = 0; i < numberOfProps << 1; i++) { storage_read_utf16_string(&pszError, handle, &pProps->pStringArr[i]); if (pszError != NULL) { break; } } if (pszError != NULL) { break; } pProps->numberOfProperties = numberOfProps; } if (pszError != NULL) { status = IO_ERROR; storageFreeError(pszError); } storageClose(&pszError, handle); storageFreeError(pszError); if (status != ALL_OK) { if (pJadProps) { free_pcsl_string_list(pJadProps->pStringArr, pJadProps->numberOfProperties << 1); } if (pJarProps) { free_pcsl_string_list(pJarProps->pStringArr, pJarProps->numberOfProperties << 1); } } return status; }
static MidpProperties midpParseMf(jchar* jchar_buffer) { MidpProperties mfsmp = {0, ALL_OK, NULL}; pcsl_string mfkey; pcsl_string mfkey_trimmed; pcsl_string mfvalue; pcsl_string mfvalue_trimmed; pcsl_string mfline; MIDPError err; pcsl_string_status rc; int countLines = 0; int index = 0; int count = 0; if (!jchar_buffer) { mfsmp.status = BAD_PARAMS; return mfsmp; } countLines = count_mf_lines(jchar_buffer); if (countLines <= 0) { REPORT_INFO(LC_AMS, "midpParseMf(): Empty manifest."); mfsmp.status = OUT_OF_MEMORY; return mfsmp; } mfsmp.pStringArr = alloc_pcsl_string_list(countLines * 2); if (mfsmp.pStringArr == NULL) { mfsmp.status = OUT_OF_MEMORY; return mfsmp; } mfsmp.numberOfProperties = countLines; for (count = 0; count < countLines * 2 ; /* count increased at the end of for */ ) { /* memory for the line is allocated here */ /* line continuation striped out */ err = readMfLine(&jchar_buffer, &mfline); if (OUT_OF_MEMORY == err) { midp_free_properties(&mfsmp); mfsmp.status = OUT_OF_MEMORY; return mfsmp; } else if (END_OF_MF == err) { /* we are done */ mfsmp.status = ALL_OK; break; } index = pcsl_string_index_of(&mfline, ':'); if (index <= 0) { mfsmp.status = BAD_MF_KEY; pcsl_string_free(&mfline); continue; } /* memory for mfkey is allocated here */ if (PCSL_STRING_OK != pcsl_string_substring(&mfline, 0, index, &mfkey)) { midp_free_properties(&mfsmp); mfsmp.status = OUT_OF_MEMORY; pcsl_string_free(&mfline); return mfsmp; } rc = pcsl_string_trim(&mfkey, &mfkey_trimmed); pcsl_string_free(&mfkey); if (PCSL_STRING_OK != rc) { mfsmp.status = OUT_OF_MEMORY; midp_free_properties(&mfsmp); pcsl_string_free(&mfline); return mfsmp; } if (pcsl_string_length(&mfkey_trimmed) < 1) { mfsmp.status = BAD_PARAMS; pcsl_string_free(&mfline); pcsl_string_free(&mfkey_trimmed); continue; } err = checkMfKeyChars(&mfkey_trimmed); if (OUT_OF_MEMORY == err) { mfsmp.status = OUT_OF_MEMORY; midp_free_properties(&mfsmp); pcsl_string_free(&mfline); pcsl_string_free(&mfkey_trimmed); return mfsmp; } else if (BAD_MF_KEY == err) { mfsmp.status = BAD_MF_KEY; pcsl_string_free(&mfline); pcsl_string_free(&mfkey_trimmed); continue; } rc = pcsl_string_substring(&mfline, index + 1, pcsl_string_length(&mfline), &mfvalue); /* free the mfline once we have got the key and value */ pcsl_string_free(&mfline); if (PCSL_STRING_OK != rc) { mfsmp.status = OUT_OF_MEMORY; midp_free_properties(&mfsmp); pcsl_string_free(&mfkey_trimmed); return mfsmp; } /* memory for value is allocated here */ rc = pcsl_string_trim(&mfvalue, &mfvalue_trimmed); pcsl_string_free(&mfvalue); if (PCSL_STRING_OK != rc) { mfsmp.status = OUT_OF_MEMORY; midp_free_properties(&mfsmp); pcsl_string_free(&mfkey_trimmed); return mfsmp; } if (pcsl_string_is_null(&mfvalue_trimmed)) { mfsmp.status = NULL_LEN; pcsl_string_free(&mfkey_trimmed); continue; } err = checkMfValueChars(&mfvalue_trimmed); if (OUT_OF_MEMORY == err) { mfsmp.status = OUT_OF_MEMORY; midp_free_properties(&mfsmp); pcsl_string_free(&mfkey_trimmed); pcsl_string_free(&mfvalue_trimmed); return mfsmp; } else if (BAD_MF_VALUE == err) { mfsmp.status = BAD_MF_VALUE; pcsl_string_free(&mfkey_trimmed); pcsl_string_free(&mfvalue_trimmed); continue; } printPcslStringWithMessage("midpParseMf()", &mfkey_trimmed); printPcslStringWithMessage(" = ", &mfvalue_trimmed); /* Store key:value pair. */ mfsmp.pStringArr[count] = mfkey_trimmed; mfsmp.pStringArr[count+1] = mfvalue_trimmed; count += 2; } /* end of for */ mfsmp = verifyMfMustProperties(mfsmp); REPORT_INFO3(LC_AMS, "End of midpParseMf: Status=%d, count=%d, countLines=%d", mfsmp.status, count, countLines); return mfsmp; } /* end of midpParseMf */
/** * Retrieves the list of strings in a file. * The file has the number of strings at the front, each string * is a length and the jchars. * * @param ppszError pointer to character string pointer to accept an error * @param pFilename name of the file of strings * @param paList pointer to an array of pcsl_strings, free with * free_pcsl_string_list * @param pStringNum number of strings if successful (can be 0) * * @return error code (ALL_OK if successful) */ static MIDPError get_string_list(char** ppszError, const pcsl_string* pFilename, pcsl_string** paList, int* pStringNum) { char* pszTemp; int i = 0; int handle; int numberOfStrings = 0; pcsl_string* pStrings = NULL; MIDPError status = ALL_OK; *ppszError = NULL; *paList = NULL; *pStringNum = 0; handle = storage_open(ppszError, pFilename, OPEN_READ); if (*ppszError != NULL) { return IO_ERROR; } do { storageRead(ppszError, handle, (char*)&numberOfStrings, sizeof (numberOfStrings)); if (*ppszError != NULL) { status = IO_ERROR; break; } if (numberOfStrings == 0) { break; } pStrings = alloc_pcsl_string_list(numberOfStrings); if (pStrings == NULL) { status = OUT_OF_MEMORY; break; } for (i = 0; i < numberOfStrings; i++) { pStrings[i] = PCSL_STRING_NULL; } for (i = 0; i < numberOfStrings; i++) { storage_read_utf16_string(ppszError, handle, &pStrings[i]); if (*ppszError != NULL) { status = IO_ERROR; break; } } if (i != numberOfStrings) { status = SUITE_CORRUPTED_ERROR; break; } } while (0); storageClose(&pszTemp, handle); storageFreeError(pszTemp); if (status == ALL_OK) { *paList = pStrings; *pStringNum = numberOfStrings; } else if (pStrings != NULL) { free_pcsl_string_list(pStrings, i); } return status; }
static MidpProperties midpParseJad(jchar* jchar_buffer) { MidpProperties jadsmp = {0, ALL_OK, NULL}; pcsl_string jadkey; pcsl_string jadkey_trimmed; pcsl_string jadvalue; pcsl_string jadvalue_trimmed; pcsl_string jadline; MIDPError err; pcsl_string_status rc; int countLines = 0; jint index = 0; int count = 0; if (!jchar_buffer) { jadsmp.status = BAD_PARAMS; return jadsmp; } countLines = count_jad_lines(jchar_buffer); if (countLines <= 0) { REPORT_INFO(LC_AMS, "midpParseJad(): Empty jad file."); jadsmp.status = OUT_OF_MEMORY; return jadsmp; } jadsmp.pStringArr = alloc_pcsl_string_list(countLines * 2); if (jadsmp.pStringArr == NULL) { jadsmp.status = OUT_OF_MEMORY; return jadsmp; } jadsmp.numberOfProperties = countLines; for (count = 0; count < countLines * 2 ; /* count increased at the end of for */ ) { /* memory for the line is allocated here */ err = readJadLine(&jchar_buffer, &jadline); if (OUT_OF_MEMORY == err) { midp_free_properties(&jadsmp); jadsmp.status = OUT_OF_MEMORY; return jadsmp; } else if (END_OF_JAD == err) { /* we are done */ jadsmp.status = ALL_OK; break; } index = pcsl_string_index_of(&jadline, ':'); if (index <= 0) { jadsmp.status = BAD_JAD_KEY; pcsl_string_free(&jadline); continue; } /* memory for key is allocated here */ if (PCSL_STRING_OK != pcsl_string_substring(&jadline, 0, index, &jadkey)) { midp_free_properties(&jadsmp); jadsmp.status = OUT_OF_MEMORY; pcsl_string_free(&jadline); return jadsmp; } rc = pcsl_string_trim(&jadkey, &jadkey_trimmed); pcsl_string_free(&jadkey); if (PCSL_STRING_OK != rc) { jadsmp.status = OUT_OF_MEMORY; midp_free_properties(&jadsmp); pcsl_string_free(&jadline); return jadsmp; } if (pcsl_string_length(&jadkey_trimmed) < 1) { jadsmp.status = BAD_PARAMS; pcsl_string_free(&jadline); pcsl_string_free(&jadkey_trimmed); continue; } err = checkJadKeyChars(&jadkey_trimmed); if (OUT_OF_MEMORY == err) { jadsmp.status = OUT_OF_MEMORY; midp_free_properties(&jadsmp); pcsl_string_free(&jadline); pcsl_string_free(&jadkey_trimmed); return jadsmp; } else if (BAD_JAD_KEY == err) { jadsmp.status = BAD_JAD_KEY; pcsl_string_free(&jadline); pcsl_string_free(&jadkey_trimmed); continue; } rc = pcsl_string_substring(&jadline, index + 1, pcsl_string_length(&jadline), &jadvalue); /* free the jadline once we have got the key and value */ pcsl_string_free(&jadline); if (PCSL_STRING_OK != rc) { jadsmp.status = OUT_OF_MEMORY; midp_free_properties(&jadsmp); pcsl_string_free(&jadkey_trimmed); return jadsmp; } /* memory for value is allocated here */ rc = pcsl_string_trim(&jadvalue, &jadvalue_trimmed); pcsl_string_free(&jadvalue); if (PCSL_STRING_OK != rc) { jadsmp.status = OUT_OF_MEMORY; midp_free_properties(&jadsmp); pcsl_string_free(&jadkey_trimmed); return jadsmp; } if (pcsl_string_is_null(&jadvalue_trimmed)) { jadsmp.status = NULL_LEN; pcsl_string_free(&jadkey_trimmed); continue; } err = checkJadValueChars(&jadvalue_trimmed); if (OUT_OF_MEMORY == err) { jadsmp.status = OUT_OF_MEMORY; midp_free_properties(&jadsmp); pcsl_string_free(&jadkey_trimmed); pcsl_string_free(&jadvalue_trimmed); return jadsmp; } else if (BAD_JAD_VALUE == err) { jadsmp.status = BAD_JAD_VALUE; pcsl_string_free(&jadkey_trimmed); pcsl_string_free(&jadvalue_trimmed); continue; } printPcslStringWithMessage("midpParseJad()", &jadkey_trimmed); printPcslStringWithMessage("midpParseJad()", &jadvalue_trimmed); /* Store key:value pair. */ jadsmp.pStringArr[count] = jadkey_trimmed; jadsmp.pStringArr[count+1] = jadvalue_trimmed; count += 2; } /* end of for */ jadsmp = verifyJadMustProperties(jadsmp); REPORT_INFO3(LC_AMS, "End jad parsing. Status=%d, count=%d, countLines=%d.", jadsmp.status, count, countLines); return jadsmp; } /* end of midpParseJad */
/** * Returns an array of the names of record stores owned by the * MIDlet suite. * * @param filenameBase filenameBase of the suite * @param ppNames pointer to pointer that will be filled in with names * * @return number of record store names or OUT_OF_MEM_LEN */ int rmsdb_get_record_store_list(pcsl_string* filenameBase, pcsl_string* *const ppNames) { int numberOfStores; pcsl_string root; pcsl_string* pStores; pcsl_string filename; pcsl_string ascii_name = PCSL_STRING_NULL_INITIALIZER; int i; void* handle = NULL; MIDPError status; int f_errc; pcsl_string_status s_errc; /* IMPL_NOTE: how can we get it statically? */ const int dbext_len = pcsl_string_length(&DB_EXTENSION); *ppNames = NULL; /* * IMPL_NOTE: for security reasons the record store is always * located in the internal storage. */ status = buildSuiteFilename(filenameBase, &PCSL_STRING_EMPTY, -1, &root); if (status != MIDP_ERROR_NONE) { return status; } if (pcsl_string_is_null(&root)) { return 0; } numberOfStores = rmsdb_get_number_of_record_stores_int(&root); if (numberOfStores <= 0) { pcsl_string_free(&root); return numberOfStores; } pStores = alloc_pcsl_string_list(numberOfStores); if (pStores == NULL) { pcsl_string_free(&root); return OUT_OF_MEM_LEN; } handle = storage_open_file_iterator(&root); if (!handle) { pcsl_string_free(&root); return OUT_OF_MEM_LEN; } /* the main loop */ for (i=0,f_errc=0,s_errc=0;;) { f_errc = storage_get_next_file_in_iterator(&root, handle, &filename); if (0 != f_errc) { f_errc = 0; break; } if (pcsl_string_ends_with(&filename, &DB_EXTENSION)) { s_errc = pcsl_string_substring(&filename, pcsl_string_length(&root), pcsl_string_length(&filename) - dbext_len, &ascii_name); pcsl_string_free(&filename); if (PCSL_STRING_OK != s_errc ) { break; } s_errc = pcsl_esc_extract_attached(0, &ascii_name, &pStores[i]); pcsl_string_free(&ascii_name); if (PCSL_STRING_OK != s_errc ) { break; } i++; } pcsl_string_free(&filename); /* IMPL_NOTE: do we need this one? isn't it useless? */ if (i == numberOfStores) { break; } } pcsl_string_free(&root); storageCloseFileIterator(handle); if (f_errc || s_errc) { /* The loop stopped because we ran out of memory. */ free_pcsl_string_list(pStores, i); return OUT_OF_MEM_LEN; } *ppNames = pStores; return numberOfStores; }
/** * Returns all found values for specified field. Tha allowed fields are: <ul> * <li> JSR211_FIELD_ID, <li> JSR211_FIELD_TYPES, <li> JSR211_FIELD_SUFFIXES, * <li> and JSR211_FIELD_ACTIONS. </ul> * Values should be selected only from handlers accessible for given caller_id. * * @param caller_id calling application identifier. * @param field search field id * @param result output structure where result is placed to. * <br>Use @link jsr211_fillStringArray function to fill this structure. * @return status of the operation */ jsr211_result jsr211_get_all(const pcsl_string* caller_id, jsr211_field field, /*OUT*/ JSR211_RESULT_STRARRAY* result) { long current_position; int found_num, access, current_size; pcsl_string *res_buffer = NULL; pcsl_string *current_result, *last; int chr = CHR_INDEX((int)(field)); int isString; switch (record_struct[chr]) { case field_string: isString = 1; break; case field_array: isString = 0; break; default: return JSR211_FAILED; } if (open_table_file(0) != JSR211_OK) { return JSR211_FAILED; } res_buffer = alloc_pcsl_string_list(JSR211_MAX_RESULT_SET); if (res_buffer == NULL) { close_table_file(); return JSR211_FAILED; } current_position = 0; for (current_result = res_buffer, last = res_buffer + JSR211_MAX_RESULT_SET; current_result < last;) { access = check_access(caller_id, current_position, ¤t_size); if (access == -1) { break; } if (access && position_field(chr) > 0) { if (isString) { read_string(current_result); if (!findStringInArray(res_buffer, current_result - res_buffer, current_result)) { current_result++; } } else { pcsl_string *array_res = NULL, *results, *last_res; int array_length = 0; read_string_array(&array_length, &array_res); if (array_length > 0) { for (results = array_res, last_res = array_res + array_length; results < last_res && current_result < last; results++) { if (!findStringInArray(res_buffer, current_result - res_buffer, results)) { *(current_result++) = *results; *results = PCSL_STRING_NULL; } } free_pcsl_string_list(array_res, array_length); } } } storagePosition(&io_error_message, table_file, current_position); current_position += current_size; goto_next_record(); } if ((found_num = (int)(current_result - res_buffer))) { jsr211_fillStringArray(res_buffer, found_num, result); } free_pcsl_string_list(res_buffer, JSR211_MAX_RESULT_SET); close_table_file(); return JSR211_OK; }
/** * Returns an array of the names of record stores owned by the * MIDlet suite. * * @param suiteId * @param ppNames pointer to pointer that will be filled in with names * * @return number of record store names or OUT_OF_MEM_LEN */ int rmsdb_get_record_store_list(SuiteIdType suiteId, pcsl_string* *const ppNames) { int numberOfStores; pcsl_string root; pcsl_string* pStores; pcsl_string filename; pcsl_string ascii_name = PCSL_STRING_NULL_INITIALIZER; int i; void* handle = NULL; MIDPError status; int f_errc; pcsl_string_status s_errc; StorageIdType storageId; /* IMPL_NOTE: how can we get it statically? */ const int dbext_len = pcsl_string_length(&DB_EXTENSION); *ppNames = NULL; /* * IMPL Note: here is assumed that the record store is located in the same * storage as the midlet suite. This may not be true. */ status = midp_suite_get_suite_storage(suiteId, &storageId); if (status != ALL_OK) { return OUT_OF_MEM_LEN; } status = midp_suite_get_rms_filename(suiteId, storageId, -1, &PCSL_STRING_EMPTY, &root); if (status != ALL_OK) { return OUT_OF_MEM_LEN; } if (pcsl_string_is_null(&root)) { return 0; } numberOfStores = rmsdb_get_number_of_record_stores_int(&root); if (numberOfStores <= 0) { pcsl_string_free(&root); return numberOfStores; } pStores = alloc_pcsl_string_list(numberOfStores); if (pStores == NULL) { pcsl_string_free(&root); return OUT_OF_MEM_LEN; } handle = storage_open_file_iterator(&root); if (!handle) { pcsl_string_free(&root); return OUT_OF_MEM_LEN; } /* the main loop */ for(i=0,f_errc=0,s_errc=0;;) { f_errc = storage_get_next_file_in_iterator(&root, handle, &filename); if (0 != f_errc) { f_errc = 0; break; } if (pcsl_string_ends_with(&filename, &DB_EXTENSION)) { s_errc = pcsl_string_substring(&filename, pcsl_string_length(&root), pcsl_string_length(&filename) - dbext_len, &ascii_name); pcsl_string_free(&filename); if (PCSL_STRING_OK != s_errc ) { break; } s_errc = escaped_ascii_to_unicode(&ascii_name, &pStores[i]); pcsl_string_free(&ascii_name); if (PCSL_STRING_OK != s_errc ) { break; } i++; } pcsl_string_free(&filename); /* IMPL_NOTE: do we need this one? isn't it useless? */ if (i == numberOfStores) { break; } } pcsl_string_free(&root); storageCloseFileIterator(handle); if (f_errc || s_errc) { /* The loop stopped because we ran out of memory. */ free_pcsl_string_list(pStores, i); return OUT_OF_MEM_LEN; } *ppNames = pStores; return numberOfStores; }