diff --git a/.gitignore b/.gitignore
index 5bbe957..1d13f7e 100755
--- a/.gitignore
+++ b/.gitignore
@@ -19,3 +19,6 @@ plugins_install/
 peasoup_executable*/
 
 /programs/Makefile*
+
+
+*_plugin_import.cpp
\ No newline at end of file
diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index cba3133..0000000
--- a/.gitmodules
+++ /dev/null
@@ -1,4 +0,0 @@
-[submodule "qtbase"]
-	path = qtbase
-	url = https://code.qt.io/qt/qtbase.git
-	branch = v6.9.0
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..d6278f2
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,9 @@
+{
+    "files.associations": {
+        "cstdlib": "c",
+        "memory": "cpp",
+        "semaphore": "cpp",
+        "stop_token": "cpp",
+        "iostream": "cpp"
+    }
+}
\ No newline at end of file
diff --git a/DOC.md b/DOC.md
new file mode 100644
index 0000000..4b0e3f5
--- /dev/null
+++ b/DOC.md
@@ -0,0 +1,15 @@
+## `GetOpenFileNameA`
+
+- Remove function call
+- Copy custom file name into ofn->lpstrFile, ensure null termination
+- Set return value to 1
+
+## `QFileDialog::getOpenFileName`
+
+- Remove function call
+- Grab `QString` constructor from `qt6core.dll` and call it with custom file name
+
+## `QFileDialog::getOpenFileNames`
+
+- Remove function call
+- Grab `QString` constructor from `qt6core.dll` and call it with custom file name
diff --git a/README.md b/README.md
index 0f94e30..4895d5c 100644
--- a/README.md
+++ b/README.md
@@ -2,11 +2,12 @@
 
 ## DLL methods
 
-- [x] `GetOpenFileNameA`
-- [ ] `IFileOpenDialog`
+- [x] `GetOpenFileNameA` (ANSI)
+- [x] `GetOpenFileNameW` (UTF-16)
+- [x] `IFileOpenDialog`
 - [x] `QFileDialog::getOpenFileName`
 - [ ] `QFileDialog::getOpenFileNames`
-- [ ] `QFileDialog::getOpenFileUrl`
+- [x] `QFileDialog::getOpenFileUrl`
 - [ ] `QFileDialog::getOpenFileUrls`
 - [ ] `QFileDialog::getOpenFileContent`
 - [ ] `wxFileDialog`
diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt
index ace1cce..5617e55 100644
--- a/client/CMakeLists.txt
+++ b/client/CMakeLists.txt
@@ -5,12 +5,8 @@ project(CustomClient)
 find_package(DynamoRIO REQUIRED)
 
 add_library(CustomClient SHARED "${CMAKE_CURRENT_SOURCE_DIR}/src/client.c")
-
-add_definitions(-DCC_QTLIB_DLL_PATH="${CMAKE_CURRENT_SOURCE_DIR}/lib/build/release/CC_QTLib.dll")
-
-target_include_directories(CustomClient PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/lib")
-target_link_directories(CustomClient PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/lib/build/release")
-
-target_link_libraries(CustomClient drwrap drmgr CC_QTLib)
+target_link_libraries(CustomClient drwrap drmgr)
 
 configure_DynamoRIO_client(CustomClient)
+use_DynamoRIO_extension(CustomClient drwrap) 
+
diff --git a/client/lib/CC_QTLib.cpp b/client/lib/CC_QTLib.cpp
deleted file mode 100644
index 474b783..0000000
--- a/client/lib/CC_QTLib.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-#include <QtCore/qglobal.h>
-
-#include <QString>
-#include <QUrl>
-#include <QList>
-
-extern "C" Q_DECL_EXPORT void CC_QString_insert(QString **ptr, const char *str) {
-    *ptr = new QString(str);
-}
-
-extern "C" Q_DECL_EXPORT QString *CC_QString_create(const char *str) {
-    return new QString(str);
-}
-
-extern "C" Q_DECL_EXPORT void CC_QString_destroy(QString *str) {
-    delete str;
-}
-
-extern "C" Q_DECL_EXPORT void CC_QUrl_insert(QUrl **ptr, const char *str) {
-    *ptr = new QUrl(str);
-}
-
-extern "C" Q_DECL_EXPORT QUrl *CC_QUrl_create(const char *str) {
-    return new QUrl(str);
-}
-
-extern "C" Q_DECL_EXPORT void CC_QUrl_destroy(QUrl *str) {
-    delete str;
-}
-
-extern "C" Q_DECL_EXPORT QList<QString> *CC_QStringList_create() {
-    return new QList<QString>();
-}
-
-extern "C" Q_DECL_EXPORT void CC_QStringList_destroy(QList<QString> *lst) {
-    delete lst;
-}
-
-extern "C" Q_DECL_EXPORT void CC_QStringList_append(QList<QString> *lst, QString *el) {
-    lst->append(*el);
-}
-
-extern "C" Q_DECL_EXPORT QList<QUrl> *CC_QUrlList_create() {
-    return new QList<QUrl>();
-}
-
-extern "C" Q_DECL_EXPORT void CC_QUrlList_destroy(QList<QUrl> *lst) {
-    delete lst;
-}
-
-extern "C" Q_DECL_EXPORT void CC_QUrlList_append(QList<QUrl> *lst, QUrl *el) {
-    lst->append(*el);
-}
diff --git a/client/lib/CC_QTLib.h b/client/lib/CC_QTLib.h
deleted file mode 100644
index 0f8f8b1..0000000
--- a/client/lib/CC_QTLib.h
+++ /dev/null
@@ -1,85 +0,0 @@
-#pragma once
-
-void CC_QString_insert(void *ptr, const char *str);
-void *CC_QString_create(const char *str);
-void CC_QString_destroy(void *str);
-
-// QUrl
-void CC_QUrl_insert(void *ptr, const char *str);
-void *CC_QUrl_create(const char *str);
-void CC_QUrl_destroy(void *str);
-
-// QStringList
-void *CC_QStringList_create();
-void CC_QStringList_destroy(void *lst);
-void CC_QStringList_append(void *lst, void *el);
-
-// QUrlList
-void *CC_QUrlList_create(const char *str);
-void CC_QUrlList_destroy(void *lst);
-void CC_QUrlList_append(void *lst, void *el);
-
-/*
-// QString
-void (*CC_QString_insert)(void *ptr, const char *str);
-void *(*CC_QString_create)(const char *str);
-void (*CC_QString_destroy)(void *str);
-
-// QUrl
-void (*CC_QUrl_insert)(void *ptr, const char *str);
-void *(*CC_QUrl_create)(const char *str);
-void (*CC_QUrl_destroy)(void *str);
-
-// QStringList
-void *(*CC_QStringList_create)();
-void (*CC_QStringList_destroy)(void *lst);
-void (*CC_QStringList_append)(void *lst, void *el);
-
-// QUrlList
-void *(*CC_QUrlList_create)(const char *str);
-void (*CC_QUrlList_destroy)(void *lst);
-void (*CC_QUrlList_append)(void *lst, void *el);
-
-inline void CC_QTLib_load() {
-#ifndef CC_QTLIB_DLL_PATH
-#error "CC_QTLIB_DLL_PATH not defined"
-#else
-
-    HMODULE hDLL;
-
-    // hDLL = LoadLibrary("C:\\Qt\\6.9.0\\msvc2022_64\\bin\\Qt6Core.dll");
-    // if (!hDLL) {
-    //     dr_printf("failed to load %s\n", "C:\\Qt\\6.9.0\\msvc2022_64\\bin\\Qt6Core.dll");
-    //     exit(1);
-    // }
-
-    hDLL = LoadLibrary(CC_QTLIB_DLL_PATH);
-    if (!hDLL) {
-        dr_printf("failed to load %s\n", CC_QTLIB_DLL_PATH);
-        exit(1);
-    }
-
-    #define CC_QTLIB_LOAD(name) name = GetProcAddress(hDLL, #name);
-
-    CC_QTLIB_LOAD(CC_QString_insert);
-    CC_QTLIB_LOAD(CC_QString_create);
-    CC_QTLIB_LOAD(CC_QString_destroy);
-
-    CC_QTLIB_LOAD(CC_QUrl_insert);
-    CC_QTLIB_LOAD(CC_QUrl_create);
-    CC_QTLIB_LOAD(CC_QUrl_destroy);
-
-    CC_QTLIB_LOAD(CC_QStringList_create);
-    CC_QTLIB_LOAD(CC_QStringList_destroy);
-    CC_QTLIB_LOAD(CC_QStringList_append);
-
-    CC_QTLIB_LOAD(CC_QUrlList_create);
-    CC_QTLIB_LOAD(CC_QUrlList_destroy);
-    CC_QTLIB_LOAD(CC_QUrlList_append);
-
-    dr_printf("%s loaded!\n", CC_QTLIB_DLL_PATH);
-
-#endif
-
-}
-*/
diff --git a/client/lib/CC_QTLib.pro b/client/lib/CC_QTLib.pro
deleted file mode 100644
index ca59a9c..0000000
--- a/client/lib/CC_QTLib.pro
+++ /dev/null
@@ -1,5 +0,0 @@
-QT += core widgets
-TEMPLATE = lib
-TARGET = CC_QTLib
-SOURCES += CC_QTLib.cpp
-CONFIG += staticlib
diff --git a/client/src/client.c b/client/src/client.c
index dc33abc..804f9f2 100644
--- a/client/src/client.c
+++ b/client/src/client.c
@@ -1,153 +1,236 @@
 #include "dr_api.h"
+#include "dr_tools.h"
+#include "drwrap.h"
 #include "dr_ir_opnd.h"
 #include "dr_ir_instr.h"
-#include "dr_ir_opcodes_x86.h"
-#include "dr_ir_macros_x86.h"
-
-#include "CC_QTLib.h"
 
 #include <ctype.h>
 #include <string.h>
 #include <windows.h>
 #include <commdlg.h>
 #include <stdint.h>
+#include <wchar.h>
+#include <shobjidl.h>
+
+// Note: Some Qt mangled names might vary slightly by compiler version.
+// These are typical for MSVC.
+const char *MANGLED_QString_const = "??0QString@@QEAA@PEBD@Z";
+const char *MANGLED_QUrl_const = "??0QUrl@@QEAA@AEBVQString@@W4ParsingMode@0@@Z";
+const char *MANGLED_QFileDialog_getOpenFileName = "?getOpenFileName@QFileDialog@@SA?AVQString@@PEAVQWidget@@AEBV2@11PEAV2@V?$QFlags@W4Option@QFileDialog@@@@@Z";
+const char *MANGLED_QFileDialog_getOpenFileNames = "?getOpenFileNames@QFileDialog@@SA?AV?$QList@VQString@@@@PEAVQWidget@@AEBVQString@@11PEAV4@V?$QFlags@W4Option@QFileDialog@@@@@Z";
+const char *MANGLED_QFileDialog_getOpenFileUrl = "?getOpenFileUrl@QFileDialog@@SA?AVQUrl@@PEAVQWidget@@AEBVQString@@AEBV2@1PEAV4@V?$QFlags@W4Option@QFileDialog@@@@AEBV?$QList@VQString@@@@@Z";
+const char *MANGLED_QFileDialog_getOpenFileUrls = "?getOpenFileUrls@QFileDialog@@SA?AV?$QList@VQUrl@@@@PEAVQWidget@@AEBVQString@@AEBVQUrl@@1PEAV4@V?$QFlags@W4Option@QFileDialog@@@@AEBV?$QList@VQString@@@@@Z";
+const char *MANGLED_QFileDialog_getOpenFileContent = "?getOpenFileContent@QFileDialog@@SAXAEBVQString@@AEBV?$function@$$A6AXAEBVQString@@AEBVQByteArray@@@Z@std@@PEAVQWidget@@@Z";
 
 char *CUSTOM_FILE = "C:\\Users\\vboxuser\\Downloads\\spoofed_number.txt";
 
-static app_pc pc_GetOpenFileNameA = NULL;
+// Function pointers for functions we need to call ourselves
+static void (*fn_QString_const)(void *qstring, const char *str) = NULL;
+static void (*fn_QUrl_const)(void *qurl, void *qstring, int parsing_mode) = NULL;
+static LPVOID (*fn_CoTaskMemAlloc)(size_t cb) = NULL;
+static HRESULT (*fn_SHCreateItemFromParsingName)(PWSTR, void *, void *, void **);
 
-void (*QString_const)(void *, char *) = NULL;
-void (*QArray_allocate)(void *, int64_t, int64_t, int64_t, int64_t) = NULL;
-static app_pc pc_QUrl_const = NULL;
-static app_pc pc_QList_const = NULL;
+// --- drwrap Callbacks for IFileOpenDialog (COM) ---
 
-static app_pc pc_QFileDialog_getOpenFileName = NULL;
-static app_pc pc_QFileDialog_getOpenFileNames = NULL;
-static app_pc pc_QFileDialog_getOpenFileUrl = NULL;
-static app_pc pc_QFileDialog_getOpenFileUrls = NULL;
-static app_pc pc_QFileDialog_getOpenFileContent = NULL;
+struct per_thread_info
+{
+    // Information needed for COM hooking
+    IShellItem *sitem_to_wrap;
+};
 
-static void intercept_GetOpenFileNameA() {
-    void *drcontext = dr_get_current_drcontext();
+static void pre_CoCreateInstance(void *wrapctx, void **user_data);
+static void post_CoCreateInstance(void *wrapctx, void *user_data);
+static void post_IFileOpenDialog_GetResult(void *wrapctx, void *user_data);
+static void pre_IShellItem_GetDisplayName(void *wrapctx, void **user_data);
+static void pre_IFileOpenDialog_GetResult(void *wrapctx, void **user_data);
+static void pre_IFileOpenDialog_Show(void *wrapctx, void **user_data);
 
-    dr_mcontext_t mcontext = { sizeof(mcontext), DR_MC_ALL };
-    dr_get_mcontext(drcontext, &mcontext);
+static HRESULT custom_IFileDialog_Show(void *, void *);
+static HRESULT custom_IFileDialog_GetResult(void *, IShellItem **ppsitem);
 
-    OPENFILENAME *ofn = (OPENFILENAME *)mcontext.rcx;
+struct IFileOpenDialogVtbl customFODVtbl = {}; 
 
-    for (int i = 0; i < strlen(CUSTOM_FILE); i++) ofn->lpstrFile[i] = CUSTOM_FILE[i];
-    ofn->lpstrFile[strlen(CUSTOM_FILE)] = 0;
+// --- drwrap Callbacks for WinAPI Functions ---
 
-    mcontext.rax = 1;
-
-    dr_set_mcontext(drcontext, &mcontext);
-}
-
-static void intercept_QFileDialog_getOpenFileName() {
-    void *drcontext = dr_get_current_drcontext();
-
-    dr_printf("intercept_QFileDialog_getOpenFileName\n");
-
-    dr_mcontext_t mcontext = { sizeof(mcontext), DR_MC_ALL };
-    dr_get_mcontext(drcontext, &mcontext);
-
-    CC_QString_insert((void *)mcontext.rcx, CUSTOM_FILE);
-}
-
-static void intercept_QFileDialog_getOpenFileNames() {
-    void *drcontext = dr_get_current_drcontext();
-
-    dr_mcontext_t mcontext = { sizeof(mcontext), DR_MC_ALL };
-    dr_get_mcontext(drcontext, &mcontext);
-
-    // make use of QString constructor to construct return value
-    // void *QArray = (void *)mcontext.rcx;
-
-    // char QString[24];
-    // QString_const(QString, CUSTOM_FILE);
-
-    // QArray_allocate(QArray, 0x18, 8, 1, 1);
-}
-
-
-static void event_exit(void) {
-}
-
-static void event_module_load(void *drcontext, const module_data_t *mod, bool loaded) {
-    char lowerpath[MAX_PATH];
-    strcpy(lowerpath, mod->full_path);
-    for (int i = 0; i < strlen(lowerpath); i++) {
-        lowerpath[i] = tolower(lowerpath[i]);
+static void pre_GetOpenFileNameA(void *wrapctx, void **user_data)
+{
+    OPENFILENAMEA *ofn = (OPENFILENAMEA *)drwrap_get_arg(wrapctx, 0);
+    if (ofn && ofn->lpstrFile)
+    {
+        strncpy(ofn->lpstrFile, CUSTOM_FILE, ofn->nMaxFile - 1);
+        ofn->lpstrFile[ofn->nMaxFile - 1] = '\0';
     }
 
-    if (strstr(lowerpath, "qt6core.dll")) {
-        QString_const = (app_pc)dr_get_proc_address(mod->handle, "??0QString@@QEAA@PEBD@Z");
-        QArray_allocate = (app_pc)dr_get_proc_address(mod->handle, "?allocate@QArrayData@@SAPEAXPEAPEAU1@_J11W4AllocationOption@1@@Z");
-        // pc_QStringList_const = (app_pc)dr_get_proc_address(mod->handle, "??0QString@@QEAA@PEBD@Z");
-        // if (pc_QString_const) dr_printf("Found QString::QString at %p\n", pc_QString_const);
-    }
-    if (strstr(lowerpath, "qt6widgets.dll")) {
-        pc_QFileDialog_getOpenFileName = (app_pc)dr_get_proc_address(mod->handle, "?getOpenFileName@QFileDialog@@SA?AVQString@@PEAVQWidget@@AEBV2@11PEAV2@V?$QFlags@W4Option@QFileDialog@@@@@Z");
-        pc_QFileDialog_getOpenFileNames = (app_pc)dr_get_proc_address(mod->handle, "?getOpenFileNames@QFileDialog@@SA?AV?$QList@VQString@@@@PEAVQWidget@@AEBVQString@@11PEAV4@V?$QFlags@W4Option@QFileDialog@@@@@Z");
-        pc_QFileDialog_getOpenFileUrl = (app_pc)dr_get_proc_address(mod->handle, "?getOpenFileUrl@QFileDialog@@SA?AVQUrl@@PEAVQWidget@@AEBVQString@@AEBV2@1PEAV4@V?$QFlags@W4Option@QFileDialog@@@@AEBV?$QList@VQString@@@@@Z");
-        pc_QFileDialog_getOpenFileUrls = (app_pc)dr_get_proc_address(mod->handle, "?getOpenFileUrls@QFileDialog@@SA?AV?$QList@VQUrl@@@@PEAVQWidget@@AEBVQString@@AEBVQUrl@@1PEAV4@V?$QFlags@W4Option@QFileDialog@@@@AEBV?$QList@VQString@@@@@Z");
-        pc_QFileDialog_getOpenFileContent = (app_pc)dr_get_proc_address(mod->handle, "?getOpenFileContent@QFileDialog@@SAXAEBVQString@@AEBV?$function@$$A6AXAEBVQString@@AEBVQByteArray@@@Z@std@@PEAVQWidget@@@Z");
-        // if (pc_QFileDialog_getOpenFileName) dr_printf("Found QFileDialog::getOpenFileName at %p\n", pc_QFileDialog_getOpenFileName);
+    drwrap_skip_call(wrapctx, (void *)1, 0);
+}
+
+static void pre_GetOpenFileNameW(void *wrapctx, void **user_data)
+{
+    OPENFILENAMEW *ofn = (OPENFILENAMEW *)drwrap_get_arg(wrapctx, 0);
+    if (ofn && ofn->lpstrFile)
+    {
+        mbstowcs(ofn->lpstrFile, CUSTOM_FILE, ofn->nMaxFile - 1);
+        ofn->lpstrFile[ofn->nMaxFile - 1] = L'\0';
     }
 
-    if (strstr(lowerpath, "comdlg32.dll")) {
-        pc_GetOpenFileNameA = (app_pc)dr_get_proc_address(mod->handle, "GetOpenFileNameA");
-        // if (pc_GetOpenFileNameA) dr_printf("Found GetOpenFileNameA at %p\n", pc_GetOpenFileNameA);
+    drwrap_skip_call(wrapctx, (void *)1, 0);
+}
+
+// --- drwrap Callbacks for Qt Functions ---
+
+static void pre_QFileDialog_getOpenFileName(void *wrapctx, void **user_data)
+{
+    if (fn_QString_const == NULL)
+        return;
+    // The return value is passed as a pointer in the first argument (sret)
+    void *qstring_ret_ptr = (void *)drwrap_get_arg(wrapctx, 0);
+    fn_QString_const(qstring_ret_ptr, CUSTOM_FILE);
+    drwrap_skip_call(wrapctx, NULL, 0);
+}
+
+static void pre_QFileDialog_getOpenFileUrl(void *wrapctx, void **user_data)
+{
+    if (fn_QString_const == NULL || fn_QUrl_const == NULL)
+        return;
+
+    const char *prefix = "file:///";
+    char urlbuf[MAX_PATH + 10];
+    snprintf(urlbuf, sizeof(urlbuf), "%s%s", prefix, CUSTOM_FILE);
+    // Replace backslashes for URL format
+    for (char *p = urlbuf; *p; ++p)
+    {
+        if (*p == '\\')
+            *p = '/';
+    }
+
+    // Create a temporary QString for the URL
+    char local_qstring[24]; // Allocate space for a QString object on the stack
+    fn_QString_const(local_qstring, urlbuf);
+
+    // Get the return QUrl object pointer (sret)
+    void *qurl_ret_ptr = (void *)drwrap_get_arg(wrapctx, 0);
+    fn_QUrl_const(qurl_ret_ptr, local_qstring, 0); // 0 is TolerantMode
+
+    drwrap_skip_call(wrapctx, NULL, 0);
+}
+
+// --- COM Wrapping Logic ---
+
+static void pre_CoCreateInstance(void *wrapctx, void **user_data)
+{
+    // Arguments: rclsid, pUnkOuter, dwClsContext, riid, ppv
+    const IID *riid = (const IID *)drwrap_get_arg(wrapctx, 3);
+    const CLSID *rclsid = (const CLSID *)drwrap_get_arg(wrapctx, 0);
+
+    // We are only interested in the creation of a FileOpenDialog
+    if (rclsid != NULL && IsEqualIID(rclsid, &CLSID_FileOpenDialog) &&
+        riid != NULL && IsEqualIID(riid, &IID_IFileOpenDialog))
+    {
+
+        dr_printf("drwrap: Intercepting CoCreateInstance for FileOpenDialog\n");
+        // Pass the pointer to the output interface pointer (ppv) to the post-hook
+        *user_data = drwrap_get_arg(wrapctx, 4);
+    }
+    else
+    {
+        *user_data = NULL;
     }
 }
 
+static void post_CoCreateInstance(void *wrapctx, void *user_data)
+{
+    // If user_data is NULL, this wasn't the CoCreateInstance we cared about
+    if (!user_data)
+        return;
 
-static dr_emit_flags_t event_basic_block(void *drcontext, void *tag, instrlist_t *bb, bool for_trace, bool translating) {
-    instr_t *to_remove = NULL, *instr = instrlist_first(bb);
-    while (instr) {
-        instr_t *next = instr_get_next(instr);
+    HRESULT hr = (HRESULT)drwrap_get_retval(wrapctx);
+    if (SUCCEEDED(hr))
+    {
+        // The user_data is the ppv argument from the pre-hook
+        IFileOpenDialog **ppv = (IFileOpenDialog **)user_data;
+        if (ppv && *ppv)
+        {
+            IFileOpenDialog *fod = *ppv;
 
-        app_pc target = NULL;
+            customFODVtbl = *fod->lpVtbl;
+            customFODVtbl.Show = custom_IFileDialog_Show;
+            customFODVtbl.GetResult = custom_IFileDialog_GetResult;
 
-        if (instr_is_call_direct(instr)) {
-            app_pc target = instr_get_branch_target_pc(instr);
-        } else if (instr_is_call_indirect(instr)) {
-            opnd_t opnd = instr_get_src(instr, 0);
-            if (opnd_is_memory_reference(opnd)) {
-                app_pc addr = opnd_compute_address(opnd, drcontext);
-                if (addr) dr_safe_read(addr, sizeof(app_pc), &target, NULL);
-            }
+            fod->lpVtbl = &customFODVtbl;
         }
-
-        if (!target) {
-            instr = next;
-            continue;
-        }
-
-        if (target == pc_GetOpenFileNameA) {
-            // dr_printf("Call to GetOpenFileNameA detected at %p\n", instr_get_app_pc(instr));
-            dr_insert_clean_call(drcontext, bb, instr, (void *)intercept_GetOpenFileNameA, false, 0);
-            instrlist_remove(bb, instr);
-            instr_destroy(drcontext, instr);
-        }
-        else if (target == pc_QFileDialog_getOpenFileName) {
-            // dr_printf("Call to QFileDialog::getOpenFileName detected at %p\n", instr_get_app_pc(instr));
-            dr_insert_clean_call(drcontext, bb, instr, (void *)intercept_QFileDialog_getOpenFileName, false, 0);
-            instrlist_remove(bb, instr);
-            instr_destroy(drcontext, instr);
-        }
-
-        instr = next;
     }
-
-    return DR_EMIT_DEFAULT;
 }
 
-DR_EXPORT void dr_client_main(client_id_t id, int argc, const char *argv[]) {
-    dr_set_client_name("Custom DynamoRIO client", "https://gitea.cloud.lehnert.dev/ludwig/windows-binary-fuzzing");
-    dr_register_exit_event(event_exit);
+static HRESULT custom_IFileDialog_Show(void *self, void *b) {
+    return S_OK;
+}
+
+static HRESULT custom_IFileDialog_GetResult(void *self, IShellItem **ppsitem) {
+    WCHAR file[MAX_PATH];
+    mbstowcs(file, CUSTOM_FILE, MAX_PATH);
+    file[MAX_PATH - 1] = L'\0';
+
+    return fn_SHCreateItemFromParsingName(file, NULL, &IID_IShellItem, (void **)ppsitem);
+}
+
+// --- Main Events ---
+
+static void event_module_load(void *drcontext, const module_data_t *mod, bool loaded)
+{
+    // Wrap functions as their modules are loaded.
+    // This is much more efficient than iterating every basic block.
+
+#define WRAP_FUNCTION(name, pre_hook, post_hook)                                           \
+    {                                                                                      \
+        app_pc addr = (app_pc)dr_get_proc_address(mod->handle, name);                      \
+        if (addr != NULL)                                                                  \
+        {                                                                                  \
+            drwrap_wrap(addr, pre_hook, post_hook);                                        \
+            dr_printf("Wrapped %s!%s at %p\n", dr_module_preferred_name(mod), name, addr); \
+        }                                                                                  \
+    }
+
+#define GET_FUNCTION_POINTER(var, name)                                                        \
+    {                                                                                                \
+        if (var == NULL)                                                                             \
+        {                                                                                            \
+            var = (void *)dr_get_proc_address(mod->handle, name);                                      \
+            if (var != NULL)                                                                         \
+                dr_printf("Found function pointer %s in %s\n", name, dr_module_preferred_name(mod)); \
+        }                                                                                            \
+    }
+
+    // WinAPI Hooks
+    WRAP_FUNCTION("GetOpenFileNameA", pre_GetOpenFileNameA, NULL);
+    WRAP_FUNCTION("GetOpenFileNameW", pre_GetOpenFileNameW, NULL);
+    WRAP_FUNCTION("CoCreateInstance", pre_CoCreateInstance, post_CoCreateInstance);
+
+    // Qt Hooks
+    WRAP_FUNCTION(MANGLED_QFileDialog_getOpenFileName, pre_QFileDialog_getOpenFileName, NULL);
+    WRAP_FUNCTION(MANGLED_QFileDialog_getOpenFileUrl, pre_QFileDialog_getOpenFileUrl, NULL);
+
+    // Get pointers to functions we need to call ourselves
+    GET_FUNCTION_POINTER(fn_QString_const, MANGLED_QString_const);
+    GET_FUNCTION_POINTER(fn_QUrl_const, MANGLED_QUrl_const);
+    GET_FUNCTION_POINTER(fn_CoTaskMemAlloc, "CoTaskMemAlloc");
+    GET_FUNCTION_POINTER(fn_SHCreateItemFromParsingName, "SHCreateItemFromParsingName");
+    
+}
+
+static void event_exit(void)
+{
+    drwrap_exit();
+}
+
+DR_EXPORT void dr_client_main(client_id_t id, int argc, const char *argv[])
+{
+    dr_set_client_name("File Dialog Interceptor", "http://example.com/");
+
+    if (!drwrap_init())
+    {
+        DR_ASSERT_MSG(false, "drwrap_init failed");
+    }
+
     dr_register_module_load_event(event_module_load);
-    dr_register_bb_event(event_basic_block);
-
-    // CC_QTLib_load();
-}
+    dr_register_exit_event(event_exit);
+}
\ No newline at end of file
diff --git a/programs/build.bat b/programs/build.bat
index ac1802c..60b4a41 100644
--- a/programs/build.bat
+++ b/programs/build.bat
@@ -2,6 +2,8 @@ cl /Fe:compiled\Foo.exe source\Foo.c /Zi /Od /link /MACHINE:X64
 
 cl /Fe:compiled\GetOpenFileNameA.exe comdlg32.lib source\GetOpenFileNameA.c /Zi /Od /link /MACHINE:X64
 
+cl /Fe:compiled\GetOpenFileNameW.exe comdlg32.lib source\GetOpenFileNameA.c /Zi /Od /link /MACHINE:X64
+
 cl /Fe:compiled\IFileDialog.exe uuid.lib ole32.lib source\IFileDialog.c /Zi /Od /link /MACHINE:X64
 
 qmake source\QT_getOpenFileContent.pro
diff --git a/programs/compiled/Foo.exe b/programs/compiled/Foo.exe
index 84dc300..1533ecd 100644
Binary files a/programs/compiled/Foo.exe and b/programs/compiled/Foo.exe differ
diff --git a/programs/compiled/GetOpenFileNameA.exe b/programs/compiled/GetOpenFileNameA.exe
index a2eadc4..92624bb 100644
Binary files a/programs/compiled/GetOpenFileNameA.exe and b/programs/compiled/GetOpenFileNameA.exe differ
diff --git a/programs/compiled/GetOpenFileNameW.exe b/programs/compiled/GetOpenFileNameW.exe
new file mode 100644
index 0000000..b29a566
Binary files /dev/null and b/programs/compiled/GetOpenFileNameW.exe differ
diff --git a/programs/compiled/IFileDialog.exe b/programs/compiled/IFileDialog.exe
index 62e52c7..9ecf569 100644
Binary files a/programs/compiled/IFileDialog.exe and b/programs/compiled/IFileDialog.exe differ
diff --git a/programs/compiled/QT_TestLib.exe b/programs/compiled/QT_TestLib.exe
index 49d8c06..11d00b7 100644
Binary files a/programs/compiled/QT_TestLib.exe and b/programs/compiled/QT_TestLib.exe differ
diff --git a/programs/compiled/QT_getOpenFileContent.exe b/programs/compiled/QT_getOpenFileContent.exe
index 1fda529..3d37422 100644
Binary files a/programs/compiled/QT_getOpenFileContent.exe and b/programs/compiled/QT_getOpenFileContent.exe differ
diff --git a/programs/compiled/QT_getOpenFileName.exe b/programs/compiled/QT_getOpenFileName.exe
index 870758f..00e2a38 100644
Binary files a/programs/compiled/QT_getOpenFileName.exe and b/programs/compiled/QT_getOpenFileName.exe differ
diff --git a/programs/compiled/QT_getOpenFileNames.exe b/programs/compiled/QT_getOpenFileNames.exe
index 6e8b15c..69bb7d6 100644
Binary files a/programs/compiled/QT_getOpenFileNames.exe and b/programs/compiled/QT_getOpenFileNames.exe differ
diff --git a/programs/compiled/QT_getOpenFileUrl.exe b/programs/compiled/QT_getOpenFileUrl.exe
index 8659993..490c8e1 100644
Binary files a/programs/compiled/QT_getOpenFileUrl.exe and b/programs/compiled/QT_getOpenFileUrl.exe differ
diff --git a/programs/compiled/QT_getOpenFileUrls.exe b/programs/compiled/QT_getOpenFileUrls.exe
index cd46915..7d4ddbe 100644
Binary files a/programs/compiled/QT_getOpenFileUrls.exe and b/programs/compiled/QT_getOpenFileUrls.exe differ
diff --git a/programs/source/GetOpenFileNameA.c b/programs/source/GetOpenFileNameA.c
index cfb6b1f..28ca4ea 100644
--- a/programs/source/GetOpenFileNameA.c
+++ b/programs/source/GetOpenFileNameA.c
@@ -15,9 +15,10 @@ int main() {
         .Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST
     };
 
-    int res = GetOpenFileName(&ofn);
+    int res = GetOpenFileNameA(&ofn);
+
     if (!res) {
-        puts("GetOpenFileName(...) failed!");
+        puts("GetOpenFileNameA(...) failed!");
         exit(1);
     }
 
diff --git a/programs/source/GetOpenFileNameW.c b/programs/source/GetOpenFileNameW.c
new file mode 100644
index 0000000..082c60c
--- /dev/null
+++ b/programs/source/GetOpenFileNameW.c
@@ -0,0 +1,42 @@
+#include <windows.h>
+#include <commdlg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <wchar.h>
+
+int main() {
+    wchar_t file[MAX_PATH] = {0};
+    
+    OPENFILENAME ofn = {
+        .lStructSize = sizeof(ofn),
+        .lpstrFilter = "All Files\0*.*\0",
+        .lpstrFile = file,
+        .nMaxFile = MAX_PATH,
+        .lpstrTitle = "Select File",
+        .Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST
+    };
+
+    int res = GetOpenFileNameW(&ofn);
+    if (!res) {
+        puts("GetOpenFileNameW(...) failed!");
+        exit(1);
+    }
+
+    char ansiFile[MAX_PATH];
+    wcstombs(ansiFile, ofn.lpstrFile, MAX_PATH);
+
+    FILE *f = fopen(ansiFile, "r");
+    if (!f) {
+        perror("fopen(...)");
+        exit(1);
+    }
+
+    long input;
+    if (fscanf(f, "%ld", &input) != 1) {
+        puts("fscanf(...) failed to scan input number");
+        exit(1);
+    }
+
+    printf("%ld\n", 2 * input);
+    return 0;
+}
diff --git a/programs/source/QT_getOpenFileContent.cpp b/programs/source/QT_getOpenFileContent.cpp
index ccdb171..4d786ad 100644
--- a/programs/source/QT_getOpenFileContent.cpp
+++ b/programs/source/QT_getOpenFileContent.cpp
@@ -9,16 +9,9 @@
 int main(int argc, char *argv[]) {
     QApplication app(argc, argv);
     
-    QSemaphore sem(1);
-    sem.acquire();
-    
-    int returnCode = -1;
-    
-    auto fileContentReady = [&returnCode, &sem](const QString &fileName, const QByteArray &fileContent) {
+    auto fileContentReady = [](const QString &fileName, const QByteArray &fileContent) {
         if (fileName.isEmpty() || !QFile(fileName).exists()) {
             std::cerr << "Failed to open file" << std::endl;
-            returnCode = 1;
-            sem.release();
             return;
         }
         
@@ -30,28 +23,11 @@ int main(int argc, char *argv[]) {
         int number = line.toInt(&ok);
         if (!ok) {
             std::cerr << "Failed to read integer from file content" << std::endl;
-            returnCode =  1;
-            sem.release();
             return;
         }
         
         std::cout << number * 2 << std::endl;
-        returnCode = 0;
-        sem.release();
     };
     
     QFileDialog::getOpenFileContent("All Files (*.*)", fileContentReady);
-    
-    QThread *thread = QThread::create([&sem, &returnCode] () {
-        sem.acquire();
-        if (returnCode == -1) {
-            std::cerr << "Failed to open file dialog" << std::endl;
-            return 1;
-        }
-        
-        return returnCode;
-    });
-    thread->start();
-    
-    // TODO: currently does not work
 }
\ No newline at end of file
diff --git a/qtbase b/qtbase
deleted file mode 160000
index 2598674..0000000
--- a/qtbase
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 25986746947798e1a22d0830d3bcb11a55fcd3ae
diff --git a/setup.bat b/setup.bat
index 4f0b687..e1cbc4b 100644
--- a/setup.bat
+++ b/setup.bat
@@ -3,62 +3,7 @@
 if not exist "qtbase" git submodule update --init
 
 cd qtbase
-.\configure.bat ^
-  -platform win32-msvc ^
-  -prefix .\build ^
-  -opensource ^
-  -static ^
-  -release ^
-  -confirm-license ^
-  -no-openssl ^
-  -no-ssl ^
-  -no-opengl ^
-  -skip qtcharts ^
-  -skip qtwebengine ^
-  -skip qtconnectivity ^
-  -skip qttools ^
-  -skip qtlottie ^
-  -skip qtimageformats ^
-  -skip qtdeclarative ^
-  -skip qtsvg ^
-  -skip qtwayland ^
-  -nomake examples ^
-  -nomake tests ^
-  -optimize-size ^
-  -skip qdoc ^
-  -skip qtactiveqt ^
-  -skip qtcharts ^
-  -skip qtcoap ^
-  -skip qtdatavis3d ^
-  -skip qtfeedback ^
-  -skip qtgamepad ^
-  -skip qtgraphicaleffects ^
-  -skip qtgrpc ^
-  -skip qthttpserver ^
-  -skip qtlocation ^
-  -skip qtlottie ^
-  -skip qtmultimedia ^
-  -skip qtnetworkauth ^
-  -skip qtpim ^
-  -skip qtpositioning ^
-  -skip qtquick3d ^
-  -skip qtremoteobjects ^
-  -skip qtscxml ^
-  -skip qtsensors ^
-  -skip qtserialbus ^
-  -skip qtserialport ^
-  -skip qtspeech ^
-  -skip qtsvg ^
-  -skip qttools ^
-  -skip qttranslations ^
-  -skip qtvirtualkeyboard ^
-  -skip qtwebchannel ^
-  -skip qtwebengine ^
-  -skip qtwebsockets ^
-  -skip qtwebview ^
-  -skip qtx11extras ^
-  -skip qtxmlpatterns
-#.\configure.bat -release -platform win32-msvc -prefix .\build -opensource -confirm-license -nomake tests -nomake examples
+.\configure.bat -static -release -platform win32-msvc -prefix .\build -opensource -confirm-license -nomake tests -nomake examples
 
 cmake --build . --parallel
 cmake --install .