private bool TryGetRow()

in SqliteVisualizer/SqliteVisualizer/SqliteFuncEvalQuery.cs [344:447]


        private bool TryGetRow(out string[] row)
        {
            // Move to the next row
            bool moreRows = false;
            var exprs = new List<DkmLanguageExpression>();

            try
            {
                const int SQLITE_ROW = 100;
                SqliteVisualizerException ex = null;
                DkmWorkList workList = DkmWorkList.Create(null);
                DkmLanguageExpression expr = this.AddFuncEval(
                    workList,
                    $"sqlite3_step(*(sqlite3_stmt **){this.procMemForQuery})",
                    (r) =>
                    {
                        DkmSuccessEvaluationResult suc;
                        if (!this.VerifySuccess(r, out suc))
                        {
                            ex = new SqliteVisualizerException(Resources.ErrMsg_FuncEvalFailed, r.FullName);
                            return;
                        }

                        moreRows = SQLITE_ROW == (int)suc.Address.Value;
                    });

                exprs.Add(expr);
                workList.Execute();

                if (ex != null)
                {
                    throw ex;
                }
            }
            finally
            {
                foreach (var e in exprs)
                {
                    e.Close();
                }

                exprs.Clear();
            }

            if (!moreRows)
            {
                row = new string[0];
                return false;
            }

            // Read each column in the row
            var rowLocal = new string[ColumnNames.Count()];
            try
            {
                SqliteVisualizerException ex = null;
                DkmProcess process = this.inspectionContext.Thread.Process;
                DkmWorkList workList = DkmWorkList.Create(null);
                for (int i = 0; i < rowLocal.Length; i++)
                {
                    var i_local = i;
                    var e = this.AddFuncEval(
                        workList,
                        $"sqlite3_column_text(*(sqlite3_stmt **){this.procMemForQuery}, {i})",
                        (r) =>
                        {
                            DkmSuccessEvaluationResult suc;
                            if (!this.VerifySuccess(r, out suc))
                            {
                                ex = ex ?? new SqliteVisualizerException(Resources.ErrMsg_FuncEvalFailed, r.FullName);
                                return;
                            }

                            ulong address = suc.Address.Value;
                            byte[] stringMaybe = process.ReadMemoryString(address, DkmReadMemoryFlags.None, 1, 1024);
                            int len = stringMaybe.Length;
                            if (len > 0)
                            {
                                // The debugger null terminates all strings, but encoding doesn't strip null when creating a string
                                len--;
                                rowLocal[i_local] = Encoding.UTF8.GetString(stringMaybe, 0, len);
                            }
                        });

                    exprs.Add(e);
                }

                workList.Execute();

                if (ex != null)
                {
                    throw ex;
                }
            }
            finally
            {
                foreach (var e in exprs)
                {
                    e.Close();
                }
            }

            row = rowLocal;
            return true;
        }