Skip to content
This repository was archived by the owner on May 24, 2026. It is now read-only.

Commit 1442b60

Browse files
committed
test
1 parent 0bb3fe9 commit 1442b60

2 files changed

Lines changed: 82 additions & 30 deletions

File tree

msi-interop/database.c

Lines changed: 38 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "handle_table.h"
77
#include "string_utils.h"
88
#include "libmsi.h"
9+
#include "msipriv.h"
910
#include <glib.h>
1011
#include <string.h>
1112
#include <stdint.h>
@@ -233,15 +234,23 @@ MsiDatabaseGetPrimaryKeysA(MSIHANDLE hDatabase, LPCSTR szTableName, MSIHANDLE *p
233234
if (!db)
234235
return ERROR_INVALID_HANDLE;
235236

237+
/*
238+
* Use internal API to avoid LIBMSI_IS_DATABASE type-check macro.
239+
* Add protective ref/unref to match the public API's bracketing.
240+
*/
236241
libmsi_global_lock();
237242

238-
GError *error = NULL;
239-
LibmsiRecord *rec = libmsi_database_get_primary_keys(db, szTableName, &error);
240-
g_object_unref(db);
243+
g_object_ref(db); /* protective ref (matches public API) */
244+
245+
LibmsiRecord *rec = NULL;
246+
unsigned r = _libmsi_database_get_primary_keys(db, szTableName, &rec);
241247

242-
if (!rec) {
248+
g_object_unref(db); /* drop protective ref */
249+
g_object_unref(db); /* drop handle_table_get_typed ref */
250+
251+
if (r != LIBMSI_RESULT_SUCCESS || !rec) {
243252
libmsi_global_unlock();
244-
return gerror_to_msi(error);
253+
return ERROR_FUNCTION_FAILED;
245254
}
246255

247256
MSIHANDLE handle = handle_table_alloc(G_OBJECT(rec), HANDLE_RECORD);
@@ -285,20 +294,25 @@ MsiDatabaseIsTablePersistentA(MSIHANDLE hDatabase, LPCSTR szTableName)
285294
if (!db)
286295
return MSICONDITION_ERROR;
287296

297+
/*
298+
* Use internal API to avoid LIBMSI_IS_DATABASE type-check macro.
299+
* Add protective ref/unref to match the public API's bracketing.
300+
*/
288301
libmsi_global_lock();
289302

290-
GError *error = NULL;
291-
gboolean persistent = libmsi_database_is_table_persistent(db, szTableName, &error);
292-
g_object_unref(db);
303+
g_object_ref(db); /* protective ref (matches public API) */
304+
305+
LibmsiCondition r = _libmsi_database_is_table_persistent(db, szTableName);
306+
307+
g_object_unref(db); /* drop protective ref */
308+
g_object_unref(db); /* drop handle_table_get_typed ref */
293309

294310
libmsi_global_unlock();
295311

296-
if (error) {
297-
g_error_free(error);
312+
if (r == LIBMSI_CONDITION_NONE || r == LIBMSI_CONDITION_ERROR)
298313
return MSICONDITION_ERROR;
299-
}
300314

301-
return persistent ? MSICONDITION_TRUE : MSICONDITION_FALSE;
315+
return (r == LIBMSI_CONDITION_TRUE) ? MSICONDITION_TRUE : MSICONDITION_FALSE;
302316
}
303317

304318
MSICONDITION WINAPI
@@ -508,16 +522,23 @@ MsiDatabaseApplyTransformA(MSIHANDLE hDatabase, LPCSTR szTransformFile,
508522
if (!db)
509523
return ERROR_INVALID_HANDLE;
510524

525+
/*
526+
* Use internal API to avoid LIBMSI_IS_DATABASE type-check macro.
527+
* Add protective ref/unref to match the public API's bracketing.
528+
*/
511529
libmsi_global_lock();
512530

513-
GError *error = NULL;
514-
gboolean ok = libmsi_database_apply_transform(db, szTransformFile, &error);
515-
g_object_unref(db);
531+
g_object_ref(db); /* protective ref (matches public API) */
532+
533+
unsigned r = _libmsi_database_apply_transform(db, szTransformFile);
534+
535+
g_object_unref(db); /* drop protective ref */
536+
g_object_unref(db); /* drop handle_table_get_typed ref */
516537

517538
libmsi_global_unlock();
518539

519-
if (!ok)
520-
return gerror_to_msi(error);
540+
if (r != LIBMSI_RESULT_SUCCESS)
541+
return ERROR_FUNCTION_FAILED;
521542

522543
return ERROR_SUCCESS;
523544
}

msi-interop/query.c

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -146,13 +146,25 @@ UINT WINAPI MsiViewExecute(MSIHANDLE hView, MSIHANDLE hRecord)
146146
}
147147
}
148148

149-
/* Use internal API to avoid redundant GObject ref/unref/type-check overhead */
149+
/*
150+
* Use internal API to avoid the LIBMSI_IS_QUERY / LIBMSI_IS_RECORD
151+
* type-check macros in the public wrapper, but keep the same
152+
* g_object_ref/unref bracketing that the public API provides.
153+
* The protective ref ensures the query (and record) remain alive
154+
* even if a view operation callback indirectly drops a reference.
155+
*/
150156
libmsi_global_lock();
151157

158+
g_object_ref(query);
159+
if (rec) g_object_ref(rec);
160+
152161
unsigned r = _libmsi_query_execute(query, rec);
153162

154-
g_object_unref(query);
155-
if (rec) g_object_unref(rec);
163+
g_object_unref(query); /* drop protective ref */
164+
if (rec) g_object_unref(rec); /* drop protective ref */
165+
166+
g_object_unref(query); /* drop handle_table_get_typed ref */
167+
if (rec) g_object_unref(rec); /* drop handle_table_get_typed ref */
156168

157169
libmsi_global_unlock();
158170

@@ -178,16 +190,20 @@ UINT WINAPI MsiViewFetch(MSIHANDLE hView, MSIHANDLE *phRecord)
178190
/*
179191
* Call the internal _libmsi_query_fetch directly instead of the public
180192
* libmsi_query_fetch wrapper. The public API does g_return_val_if_fail
181-
* (LIBMSI_IS_QUERY) which dereferences GObject class pointers and an
182-
* extra g_object_ref/unref cycle -- both unnecessary since we already
183-
* hold a valid ref from handle_table_get_typed. Bypassing the public
184-
* wrapper avoids potential issues with the GObject type-check machinery.
193+
* (LIBMSI_IS_QUERY) which dereferences GObject class pointers -- bypassing
194+
* the public wrapper avoids potential issues with the GObject type-check
195+
* machinery. We add a protective g_object_ref/unref to match the public
196+
* API's bracketing, keeping the query alive during the fetch operation.
185197
*/
186198
libmsi_global_lock();
187199

200+
g_object_ref(query); /* protective ref (matches public API) */
201+
188202
LibmsiRecord *rec = NULL;
189203
unsigned ret = _libmsi_query_fetch(query, &rec);
190-
g_object_unref(query);
204+
205+
g_object_unref(query); /* drop protective ref */
206+
g_object_unref(query); /* drop handle_table_get_typed ref */
191207

192208
if (ret == NO_MORE_ITEMS) {
193209
libmsi_global_unlock();
@@ -339,12 +355,20 @@ UINT WINAPI MsiViewGetColumnInfo(MSIHANDLE hView, MSICOLINFO eColumnInfo, MSIHAN
339355
if (!query)
340356
return ERROR_INVALID_HANDLE;
341357

342-
/* Use internal API to avoid redundant GObject ref/unref/type-check overhead */
358+
/*
359+
* Use internal API to avoid the LIBMSI_IS_QUERY type-check macro in the
360+
* public wrapper. Add a protective ref to match the public API's
361+
* g_object_ref/unref bracketing.
362+
*/
343363
libmsi_global_lock();
344364

365+
g_object_ref(query); /* protective ref (matches public API) */
366+
345367
LibmsiRecord *rec = NULL;
346368
unsigned r = _libmsi_query_get_column_info(query, (LibmsiColInfo)eColumnInfo, &rec);
347-
g_object_unref(query);
369+
370+
g_object_unref(query); /* drop protective ref */
371+
g_object_unref(query); /* drop handle_table_get_typed ref */
348372

349373
if (r != LIBMSI_RESULT_SUCCESS || !rec) {
350374
libmsi_global_unlock();
@@ -373,18 +397,25 @@ UINT WINAPI MsiViewClose(MSIHANDLE hView)
373397
if (!query)
374398
return ERROR_INVALID_HANDLE;
375399

376-
/* Call the view's close operation directly instead of libmsi_query_close,
400+
/*
401+
* Call the view's close operation directly instead of libmsi_query_close,
377402
* which has a ref-count leak bug on early-return error paths (it does
378403
* g_object_ref but returns without g_object_unref when view is NULL or
379-
* view->ops->close is NULL). */
404+
* view->ops->close is NULL). We add a protective ref/unref to match the
405+
* public API's bracketing on the success path, keeping the query alive
406+
* during the close operation.
407+
*/
380408
libmsi_global_lock();
381409

410+
g_object_ref(query); /* protective ref (matches public API) */
411+
382412
LibmsiView *view = query->view;
383413
unsigned r = LIBMSI_RESULT_SUCCESS;
384414
if (view && view->ops && view->ops->close)
385415
r = view->ops->close(view);
386416

387-
g_object_unref(query);
417+
g_object_unref(query); /* drop protective ref */
418+
g_object_unref(query); /* drop handle_table_get_typed ref */
388419

389420
libmsi_global_unlock();
390421

0 commit comments

Comments
 (0)