Пример #1
0
//_________________________________________________________
_CString::_CString (unsigned long sL, bool flag)
{
    if (flag) {
        sLength = 0;
        if (sL<storageIncrement) {
            sL = storageIncrement;
        }
        sData = (char*)MemAllocate (sL*sizeof (char));
        allocatedSpace = sL;
        if (!sData) {
            warnError( -108);
        }
    } else {
        allocatedSpace = 0;
        sLength = sL;
        sData = (char*)MemAllocate (sL+1);
        if (sData) {
            memset (sData,0,sL+1);
        } else {
            sLength = 0;
            isError(0);
        }
    }
    compressionType = NOCOMPRESSION;
}
Пример #2
0
//Data constructor (1 member list)
_SimpleList::_SimpleList (long br)
{
    lLength = 1;
    laLength = MEMORYSTEP;
    lData = (long*)MemAllocate (laLength * sizeof(Ptr));
    ((long*)lData)[0]= br;
}
Пример #3
0
//Length constructor
_SimpleList::_SimpleList (unsigned long l)
{
    lLength = 0;
    laLength = (l/MEMORYSTEP + 1)*MEMORYSTEP;
    lData = (long*)MemAllocate (laLength * sizeof(Ptr));
    memset (lData,0,laLength * sizeof(Ptr));
}
Пример #4
0
static INLINE LOG_ENTRY *GetSpareEntry(VOID)
{
    if (logStatus != LOG_STATUS_ACTIVE) {
        // Logging system must be active
        return NULL;
    }
    return MemAllocate(sizeof(LOG_ENTRY));
}
Пример #5
0
static INT UserOpen(CHAR *userName, USERFILE *userFile)
{
    DB_CONTEXT *db;
    DWORD       result;
    MOD_CONTEXT *mod;

    TRACE("userName=%s userFile=%p", userName, userFile);

    if (!DbAcquire(&db)) {
        // Return UM_DELETED instead of UM_ERROR to work around a bug in ioFTPD.
        return UM_DELETED;
    }

    // Module context is required for all file operations
    mod = MemAllocate(sizeof(MOD_CONTEXT));
    if (mod == NULL) {
        result = ERROR_NOT_ENOUGH_MEMORY;
        LOG_ERROR("Unable to allocate memory for module context.");

    } else {
        // Initialize MOD_CONTEXT structure
        mod->file            = INVALID_HANDLE_VALUE;
        userFile->lpInternal = mod;

        // Open user file
        result = FileUserOpen(userFile->Uid, userFile);
        if (result != ERROR_SUCCESS) {
            LOG_WARN("Unable to open user file for \"%s\" (error %lu).", userName, result);
        } else {

            // Read database record
            result = DbUserOpen(db, userName, userFile);
            if (result != ERROR_SUCCESS) {
                LOG_WARN("Unable to open user database record for \"%s\" (error %lu).", userName, result);

                // Clean-up user file
                FileUserClose(userFile);
            }
        }

        // Free module context if the file/database open failed
        if (result != ERROR_SUCCESS) {
            MemFree(mod);
        }
    }

    DbRelease(db);

    //
    // Return UM_DELETED instead of UM_ERROR to work around a bug in ioFTPD. If
    // UM_ERROR is returned, ioFTPD frees part of the USERFILE structure and
    // may crash later on (e.g. if someone issues "SITE USERS").
    //
    SetLastError(result);
    return (result == ERROR_SUCCESS) ? UM_SUCCESS : UM_DELETED;
}
Пример #6
0
//_________________________________________________________
_THyPhyMatrix::_THyPhyMatrix(const long r, const long c, const double* d)
{
    checkPointer (mData = (double*)MemAllocate (r*c*sizeof(double)));
    mRows = r;
    mCols = c;
    for (long i = 0; i < r*c; i++,d++) {
        mData[i] = *d;
    }

}
Пример #7
0
//Assignment operator
_SimpleList _SimpleList::operator = (_SimpleList l)
{
    Clear();
    lLength  = l.lLength;
    laLength = l.laLength;
    if (laLength) {
        checkPointer (lData = (long*)MemAllocate (laLength*sizeof (Ptr)));
        if (lLength) {
            memcpy (lData,l.lData,lLength*sizeof (Ptr));
        }
    }

    return *this;
}
Пример #8
0
//_________________________________________________________
_THyPhyString::_THyPhyString(const char* characters, long length)
{
    if (characters) {
        if (length == 0) {
            while (characters[length++]) ;
            length --;
        }
        checkPointer (sData = (char*)MemAllocate (length+1));
        memcpy       (sData,characters,length+1);

    } else {
        sData   = nil;
    }
    sLength = length;
}
Пример #9
0
bool_t
PushCXT (
    peval_t pv
    )
{
    HCXTL   nhCxtl;
    PCXTL   npCxtl;
    uint    lenIn;
    uint    lenOut;

    DASSERT (pCxtl->cHCS <= mCxtl);
    if (mCxtl < pCxtl->cHCS) {
        // this is a catatrosphic error
        return (FALSE);
    }
    if (mCxtl == pCxtl->cHCS) {
        // grow CXT list

        lenIn = sizeof (CXTL) + mCxtl * sizeof (HCS);
        lenOut = sizeof (CXTL) + (mCxtl + 5) * sizeof (HCS);
        if ((nhCxtl = MemAllocate (lenOut)) == 0) {
            return (FALSE);
        }
        npCxtl = (PCXTL) MemLock (nhCxtl);
        memcpy (npCxtl, pCxtl, lenIn);
        mCxtl += 5;
        MemUnLock (hCxtl);
        MHMemFree (hCxtl);
        hCxtl = nhCxtl;
        pCxtl = npCxtl;
    }

    // in case of a constant we will return only the context information.
    // anything more than that doesn't make sense and since we
    // need to get context only information in the case of bp {..}.line
    // we needed to make this change.

    pCxtl->rgHCS[pCxtl->cHCS].hSym = pv->hSym;
    // Change for Dolphin bp functionality:
    // if pv->CXTT is non-zero, prefer it over *pCxt:
    // pv->CXTT is more specific, as it contains the exact
    // context where a symbol was found by SearchSym, while
    // pCxt just contains a context from which the symbol is
    // visible
    pCxtl->rgHCS[pCxtl->cHCS].CXT =  (pv->CXTT.hMod) ? pv->CXTT :  *pCxt;
    pCxtl->cHCS++;
    return (TRUE);
}
Пример #10
0
static DWORD GroupEventCreate(CHAR *groupName, GROUPFILE *groupFile)
{
    MOD_CONTEXT *mod;
    DWORD       result;
    INT32       groupId;

    ASSERT(groupName != NULL);
    ASSERT(groupFile != NULL);

    // Module context is required for all file operations
    mod = MemAllocate(sizeof(MOD_CONTEXT));
    if (mod == NULL) {
        result = ERROR_NOT_ENOUGH_MEMORY;
        TRACE("Unable to allocate module context.");

    } else {
        // Initialize MOD_CONTEXT structure
        mod->file = INVALID_HANDLE_VALUE;
        groupFile->lpInternal = mod;

        // Register group
        result = GroupRegister(groupName, groupFile, &groupId);
        if (result != ERROR_SUCCESS) {
            TRACE("Unable to register group (error %lu).", result);
        } else {

            // Create group file
            result = FileGroupCreate(groupId, groupFile);
            if (result != ERROR_SUCCESS) {
                TRACE("Unable to create group file (error %lu).", result);

                // Creation failed, clean-up the group file
                FileGroupDelete(groupId);
                FileGroupClose(groupFile);
                GroupUnregister(groupName);
            }
        }

        if (result != ERROR_SUCCESS) {
            // Free module context after all file operations
            MemFree(mod);
        }
    }

    return result;
}
Пример #11
0
static DWORD UserEventCreate(CHAR *userName, USERFILE *userFile)
{
    MOD_CONTEXT *mod;
    DWORD       result;
    INT32       userId;

    ASSERT(userName != NULL);
    ASSERT(userFile != NULL);

    // Module context is required for all file operations
    mod = MemAllocate(sizeof(MOD_CONTEXT));
    if (mod == NULL) {
        result = ERROR_NOT_ENOUGH_MEMORY;
        LOG_ERROR("Unable to allocate memory for module context.");

    } else {
        // Initialize MOD_CONTEXT structure
        mod->file = INVALID_HANDLE_VALUE;
        userFile->lpInternal = mod;

        // Register user
        result = UserRegister(userName, userFile, &userId);
        if (result != ERROR_SUCCESS) {
            TRACE("Unable to register user (error %lu).", result);
        } else {

            // Create user file
            result = FileUserCreate(userId, userFile);
            if (result != ERROR_SUCCESS) {
                TRACE("Unable to create user file (error %lu).", result);

                // Creation failed, clean-up the user file
                FileUserDelete(userId);
                FileUserClose(userFile);
                UserUnregister(userName);
            }
        }

        if (result != ERROR_SUCCESS) {
            // Free module context after all file operations
            MemFree(mod);
        }
    }

    return result;
}
Пример #12
0
ulong
DoGetCXTL (
    PHTM phTM,
    PHCXTL phCXTL
    )
{
    ulong       retval = EECATASTROPHIC;

    // lock the expression state structure and copy the context package

    DASSERT (*phTM != 0);
    if (*phTM != 0) {
        pExState = (pexstate_t) MemLock (*phTM);
        if ((pExState->state.parse_ok == TRUE) &&
          (pExState->state.bind_ok == TRUE)) {
            if ((hCxtl = MemAllocate (sizeof (CXTL) + 5 * sizeof (HCS))) == 0) {
                pExState->err_num = ERR_NOMEMORY;
                MemUnLock (*phTM);
                *phCXTL = hCxtl;
                return (EEGENERAL);
            } else {
                pCxtl = (PCXTL) MemLock (hCxtl);
                mCxtl = 5;
                pCxtl->CXT = pExState->cxt;
                pCxtl->cHCS = 0;

            }
            pTree = (pstree_t) MemLock (pExState->hETree);
            if (GetCXTL ((pnode_t)((bnode_t)pTree->start_node))) {
                retval = EENOERROR;
            } else {
                retval = EEGENERAL;
            }
            *phCXTL = hCxtl;
            MemUnLock (hCxtl);
            MemUnLock (pExState->hETree);
        }
        MemUnLock (*phTM);
    }
    return (retval);
}
Пример #13
0
static INT32 UserCreate(CHAR *userName)
{
    DB_CONTEXT  *db;
    MOD_CONTEXT *mod;
    DWORD       result;
    INT32       userId = -1;
    USERFILE    userFile;

    TRACE("userName=%s", userName);

    if (!DbAcquire(&db)) {
        return userId;
    }

    // Module context is required for all file operations
    mod = MemAllocate(sizeof(MOD_CONTEXT));
    if (mod == NULL) {
        result = ERROR_NOT_ENOUGH_MEMORY;
        LOG_ERROR("Unable to allocate memory for module context.");

    } else {
        // Initialize MOD_CONTEXT structure
        mod->file = INVALID_HANDLE_VALUE;

        // Initialize USERFILE structure
        ZeroMemory(&userFile, sizeof(USERFILE));
        userFile.Groups[0]      = NOGROUP_ID;
        userFile.Groups[1]      = -1;
        userFile.AdminGroups[0] = -1;
        userFile.lpInternal     = mod;

        // Read "Default.User" file
        result = FileUserDefault(&userFile);
        if (result != ERROR_SUCCESS) {
            LOG_WARN("Unable to read \"Default.User\" file (error %lu).", result);
        }

        // Register user
        result = UserRegister(userName, &userFile, &userId);
        if (result != ERROR_SUCCESS) {
            TRACE("Unable to register user (error %lu).", result);
        } else {

            // Create user file
            result = FileUserCreate(userId, &userFile);
            if (result != ERROR_SUCCESS) {
                LOG_WARN("Unable to create user file (error %lu).", result);
            } else {

                // Create database record
                result = DbUserCreate(db, userName, &userFile);
                if (result != ERROR_SUCCESS) {
                    LOG_WARN("Unable to create database record (error %lu).", result);
                }
            }

            // If the file or database creation failed, clean-up the user file
            if (result != ERROR_SUCCESS) {
                FileUserDelete(userId);
                FileUserClose(&userFile);
                UserUnregister(userName);
            }
        }

        if (result != ERROR_SUCCESS) {
            // Free module context after all file operations
            MemFree(mod);

            // Indicate an error occured by returning an invalid user ID
            userId = -1;
        }
    }

    DbRelease(db);

    SetLastError(result);
    return userId;
}
Пример #14
0
/*++

ConnectionOpen

    Opens a server connection.

Arguments:
    context - Opaque context passed to <PoolCreate>.

    data    - Pointer to a pointer that receives the DB_CONTEXT structure.

Return Values:
    If the function succeeds, the return value is nonzero (true).

    If the function fails, the return value is zero (false).

--*/
static BOOL FCALL ConnectionOpen(VOID *context, VOID **data)
{
    DB_CONTEXT          *db;
    DB_CONFIG_SERVER    *server;
    DWORD               error;
    DWORD               i;
    INT                 attempt;
    INT                 attemptMax;
    LONG                serverIndex;
    LONG                serverNextIndex;
    MYSQL               *connection;
    my_bool             optReconnect;
    UINT                optTimeout;

    UNREFERENCED_PARAMETER(context);
    ASSERT(data != NULL);
    TRACE("context=%p data=%p", context, data);

    db = MemAllocate(sizeof(DB_CONTEXT));
    if (db == NULL) {
        LOG_ERROR("Unable to allocate memory for database context.");

        error = ERROR_NOT_ENOUGH_MEMORY;
        goto failed;
    }
    ZeroMemory(db, sizeof(DB_CONTEXT));

    //
    // Have the MySQL client library allocate the handle structure for us. This is
    // in case the MYSQL structure changes in a future version of the client library.
    //
    db->handle = mysql_init(NULL);
    if (db->handle == NULL) {
        LOG_ERROR("Unable to allocate memory for MySQL handle.");

        error = ERROR_NOT_ENOUGH_MEMORY;
        goto failed;
    }

    // If the maximum number of attempts were not specified, try all servers
    if (dbConfigGlobal.connAttempts > 0) {
        attemptMax = dbConfigGlobal.connAttempts;
    } else {
        attemptMax = dbConfigServerCount;
    }

    for (attempt = 0; attempt < attemptMax; attempt++) {
        // Use the most recent server for the connection attempt
        serverIndex = dbIndex;
        server      = &dbConfigServers[serverIndex];

        TRACE("Connecting to server #%d [%s] on attempt %lu/%lu.",
            serverIndex, server->name, attempt+1, attemptMax);

        // Set connection options
        optTimeout = (UINT)dbConfigGlobal.connTimeout;
        if (mysql_options(db->handle, MYSQL_OPT_CONNECT_TIMEOUT, &optTimeout) != 0) {
            TRACE("Failed to set connection timeout option.");
        }

        optReconnect = FALSE;
        if (mysql_options(db->handle, MYSQL_OPT_RECONNECT, &optReconnect) != 0) {
            TRACE("Failed to set reconnection option.");
        }

        if (server->compression) {
            if (mysql_options(db->handle, MYSQL_OPT_COMPRESS, 0) != 0) {
                TRACE("Failed to set compression option.");
            }
        }

        if (server->sslEnable) {
            //
            // This function always returns 0. If the SSL setup is incorrect,
            // the call to mysql_real_connect() will return an error.
            //
            mysql_ssl_set(db->handle, server->sslKeyFile, server->sslCertFile,
                server->sslCAFile, server->sslCAPath, server->sslCiphers);
        }

        // Attempt connection with server
        connection = mysql_real_connect(db->handle,
            server->host, server->user, server->password,
            server->database, server->port, NULL, CLIENT_INTERACTIVE);

        if (connection == NULL) {
            LOG_ERROR("Unable to connect to server [%s]: %s",
                server->name, mysql_error(db->handle));

        } else if (mysql_get_server_version(db->handle) < 50019) {
            LOG_ERROR("Unsupported version of MySQL Server [%s]: running v%s, must be v5.0.19 or newer.",
                server->name, mysql_get_server_info(db->handle));

        } else {
            // Pointer values should be the same as from mysql_init()
            ASSERT(connection == db->handle);

            // Allocate pre-compiled statement structures
            for (i = 0; i < ELEMENT_COUNT(db->stmt); i++) {
                db->stmt[i] = mysql_stmt_init(db->handle);
                if (db->stmt[i] == NULL) {
                    LOG_ERROR("Unable to allocate memory for statement structure.");

                    error = ERROR_NOT_ENOUGH_MEMORY;
                    goto failed;
                }
            }

            // Successfully connected, set the global server index
            InterlockedExchange(&dbIndex, serverIndex);

            // Update context's server index and time stamps
            db->index = serverIndex;
            GetSystemTimeAsFileTime(&db->created.fileTime);
            db->used.value = db->created.value;

            LOG_INFO("Connected to %s [%s], running MySQL Server v%s.",
                mysql_get_host_info(db->handle), server->name,
                mysql_get_server_info(db->handle));

            *data = db;
            return TRUE;
        }

        // Unsuccessful connection, continue to the next server
        serverNextIndex = serverIndex + 1;
        if (serverNextIndex >= (LONG)dbConfigServerCount) {
            serverNextIndex = 0;
        }

        //
        // Compare the current server index before swapping values in the
        // event that another thread has already changed the index.
        //
        InterlockedCompareExchange(&dbIndex, serverNextIndex, serverIndex);
    }

    // Unable to connect to any servers
    error = ERROR_CONNECTION_REFUSED;

failed:
    if (db != NULL) {
        ConnectionClose(NULL, db);
    }
    SetLastError(error);
    return FALSE;
}
Пример #15
0
static INT GroupOpen(CHAR *groupName, GROUPFILE *groupFile)
{
    DB_CONTEXT *db;
    DWORD       result;
    MOD_CONTEXT *mod;

    ASSERT(groupName != NULL);
    ASSERT(groupFile != NULL);
    TRACE("groupName=%s groupFile=%p", groupName, groupFile);

    if (!DbAcquire(&db)) {
        // Return GM_DELETED instead of GM_ERROR to work around a bug in ioFTPD.
        return GM_DELETED;
    }

    // Module context is required for all file operations
    mod = MemAllocate(sizeof(MOD_CONTEXT));
    if (mod == NULL) {
        result = ERROR_NOT_ENOUGH_MEMORY;
        LOG_ERROR("Unable to allocate memory for module context.");

    } else {
        // Initialize MOD_CONTEXT structure
        mod->file            = INVALID_HANDLE_VALUE;
        groupFile->lpInternal = mod;

        // Open group file
        result = FileGroupOpen(groupFile->Gid, groupFile);
        if (result != ERROR_SUCCESS) {
            LOG_WARN("Unable to open group file for \"%s\" (error %lu).", groupName, result);
        } else {

            // Read database record
            result = DbGroupOpen(db, groupName, groupFile);
            if (result == ERROR_SUCCESS) {
                // Make sure we haven't wiped out the module context pointer
                ASSERT(groupFile->lpInternal != NULL);

            } else {
                LOG_WARN("Unable to open group database record for \"%s\" (error %lu).", groupName, result);

                // Clean-up group file
                FileGroupClose(groupFile);
            }
        }

        // Free module context if the file/database open failed
        if (result != ERROR_SUCCESS) {
            MemFree(mod);
        }
    }

    DbRelease(db);

    //
    // Return GM_DELETED instead of GM_ERROR to work around a bug in ioFTPD. If
    // GM_ERROR is returned, ioFTPD frees part of the GROUPFILE structure and
    // may crash later on (e.g. if someone issues "SITE GROUPS").
    //
    SetLastError(result);
    return (result == ERROR_SUCCESS) ? GM_SUCCESS : GM_DELETED;
}
Пример #16
0
static INT32 GroupCreate(CHAR *groupName)
{
    DB_CONTEXT  *db;
    MOD_CONTEXT *mod;
    DWORD       result;
    INT32       groupId = -1;
    GROUPFILE    groupFile;

    ASSERT(groupName != NULL);
    TRACE("groupName=%s", groupName);

    if (!DbAcquire(&db)) {
        return groupId;
    }

    // Module context is required for all file operations
    mod = MemAllocate(sizeof(MOD_CONTEXT));
    if (mod == NULL) {
        result = ERROR_NOT_ENOUGH_MEMORY;
        LOG_ERROR("Unable to allocate memory for module context.");

    } else {
        // Initialize MOD_CONTEXT structure
        mod->file = INVALID_HANDLE_VALUE;

        // Initialize GROUPFILE structure
        ZeroMemory(&groupFile, sizeof(GROUPFILE));
        groupFile.lpInternal = mod;

        // Read "Default.Group" file
        result = FileGroupDefault(&groupFile);
        if (result != ERROR_SUCCESS) {
            LOG_WARN("Unable to read \"Default.Group\" file (error %lu).", result);
        }

        // Register group
        result = GroupRegister(groupName, &groupFile, &groupId);
        if (result != ERROR_SUCCESS) {
            TRACE("Unable to register group (error %lu).", result);
        } else {

            // Create group file
            result = FileGroupCreate(groupId, &groupFile);
            if (result != ERROR_SUCCESS) {
                LOG_WARN("Unable to create group file (error %lu).", result);
            } else {

                // Create database record
                result = DbGroupCreate(db, groupName, &groupFile);
                if (result != ERROR_SUCCESS) {
                    LOG_WARN("Unable to create database record (error %lu).", result);
                }
            }

            // Make sure we haven't wiped out the module context pointer
            ASSERT(groupFile.lpInternal != NULL);

            // If the file or database creation failed, clean-up the group file
            if (result != ERROR_SUCCESS) {
                FileGroupDelete(groupId);
                FileGroupClose(&groupFile);
                GroupUnregister(groupName);
            }
        }

        if (result != ERROR_SUCCESS) {
            // Free module context after all file operations
            MemFree(mod);

            // Indicate an error occured by returning an invalid group ID
            groupId = -1;
        }
    }

    DbRelease(db);

    SetLastError(result);
    return groupId;
}
Пример #17
0
EESTATUS
GetExpr (
    uint radix,
    PEEHSTR phStr,
    ulong  *pEnd
    )
{
    EESTATUS    retval = EENOMEMORY;
    char *pStr;
    char *pExprStr;
    HDEP        hExprStr;
    int         len;
    ulong       strIndex;
    UINT nLen;

    Unreferenced( radix );

    //M00KLUDGE - this routine will eventuall have to walk the bound tree
    //            and format the expression because of ambiguous expressions

    // use the saved original string if there is one
    // (in case the expression has been modified)

    if (pExState->hExStrSav) {
        hExprStr = pExState->hExStrSav;
        len = pExState->ExLenSav;
        strIndex = pExState->strIndexSav;
    } else {
        hExprStr = pExState->hExStr;
        len = pExState->ExLen;
        strIndex = pExState->strIndex;
    }

    pExprStr = (char *) MemLock (hExprStr);

    nLen = len+1;
    if (((*phStr = MemAllocate (nLen)) != 0)) {
        // the expression has been bound and memory allocated
        char        tempBuf[TYPESTRMAX];
        UINT        nb;
        UINT        nIndex = 0;
        BOOL        fHSYM;
        char *psz;
        ulong       nAdj = 0;

        pStr = (char *) MemLock (*phStr);
        for (psz = pExprStr; (psz < pExprStr + len) && *psz; psz = _tcsinc (psz)) {
            fHSYM = FALSE;
            if (*psz == HSYM_MARKER) {
                HSYM hSym = GetHSYMFromHSYMCode(psz + 1);
                psz += HSYM_CODE_LEN;  // skip embedded HSYM code
                fHSYM = TRUE;
                DASSERT (hSym);
                if (GetNameFromHSYM(tempBuf, hSym) == FALSE) {
                    pExState->err_num = ERR_INTERNAL;
                    MemUnLock(*phStr);
                    MemUnLock(hExprStr);
                    return EEGENERAL;
                }
                nb = _tcslen(tempBuf);
                // compute adjustment for strIndex:
                // if an HSYM is to the left of strIndex,
                // strIndex needs to be adjusted
                if (psz <= pExprStr + strIndex)
                    nAdj += (nb - sizeof (char) - HSYM_CODE_LEN);
            } else {
                nb = 1;
            }

            // check if there is space in the buffer and
            // copy nb characters to the destination string

            if (nIndex + nb > nLen-1) {
                // there is not enough space, grow buffer
                MemUnLock(*phStr);
                nLen += NAMESTRMAX;
                if ((*phStr = MemReAlloc(*phStr, nLen)) == 0){
                    MemUnLock(hExprStr);
                    return EENOMEMORY;
                }
                pStr = (char *) MemLock (*phStr);
            }
            if (fHSYM) {
                // copy name from tembBuf
                memcpy(pStr+nIndex, tempBuf, nb);
                nIndex += nb;
            } else {
                // copy a single character from pExprStr
                _tccpy (pStr + nIndex, psz);
                nIndex += _tclen (psz);
            }
        }
        pStr[nIndex++] = 0;
        MemUnLock (*phStr);

        // Reallocate the buffer in case it is too large
        DASSERT (nIndex <= nLen);
        if (nIndex < nLen &&
            (*phStr = MemReAlloc(*phStr, nIndex)) == 0){
            MemUnLock(hExprStr);
            return EENOMEMORY;
        }
        retval = EENOERROR;
        *pEnd = strIndex + nAdj;
    }
    MemUnLock (hExprStr);

    return retval;
}