better handling of already-initialized COM
Some checks failed
pyrite-dev/milsko/pipeline/head There was a failure building this commit

This commit is contained in:
IoI_xD 2026-07-22 13:31:19 -07:00
commit fbbf52af04

View file

@ -12,27 +12,26 @@ typedef struct userdata {
static struct symtbl {
void* lib_dwmapi;
void *shell32lib;
void *ole32lib;
void *urlmonlib;
void* shell32lib;
void* ole32lib;
void* urlmonlib;
MwBool has_drag_and_drop;
HRESULT(WINAPI* DwmSetWindowAttribute)(HWND hwnd, DWORD dwAttribute, LPCVOID pvAttribute, DWORD cbAttribute);
UINT (WINAPI *DragQueryFileW)(HDROP hDrop,UINT iFile,LPWSTR lpszFile,UINT cch);
UINT (WINAPI *DragQueryFileA)(HDROP hDrop,UINT iFile,LPSTR lpszFile,UINT cch);
void (WINAPI *ReleaseStgMedium)(LPSTGMEDIUM unnamedParam1);
HRESULT (WINAPI *OleInitialize)(LPVOID pvReserved);
HRESULT (WINAPI *RegisterDragDrop)(HWND hwnd, LPDROPTARGET pDropTarget);
HRESULT (WINAPI *FindMimeFromData)(
LPBC pBC,
LPCWSTR pwzUrl,
LPVOID pBuffer,
DWORD cbSize,
LPCWSTR pwzMimeProposed,
DWORD dwMimeFlags,
LPWSTR *ppwzMimeOut,
_Reserved_ DWORD dwReserved
);
UINT(WINAPI* DragQueryFileW)(HDROP hDrop, UINT iFile, LPWSTR lpszFile, UINT cch);
UINT(WINAPI* DragQueryFileA)(HDROP hDrop, UINT iFile, LPSTR lpszFile, UINT cch);
void(WINAPI* ReleaseStgMedium)(LPSTGMEDIUM unnamedParam1);
HRESULT(WINAPI* OleInitialize)(LPVOID pvReserved);
HRESULT(WINAPI* RegisterDragDrop)(HWND hwnd, LPDROPTARGET pDropTarget);
HRESULT(WINAPI* FindMimeFromData)(
LPBC pBC,
LPCWSTR pwzUrl,
LPVOID pBuffer,
DWORD cbSize,
LPCWSTR pwzMimeProposed,
DWORD dwMimeFlags,
LPWSTR* ppwzMimeOut,
_Reserved_ DWORD dwReserved);
} wsymtbl;
static int is_plgblt_reliable = 0;
@ -441,7 +440,7 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) {
SetWindowPos(r->gdi.hWnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
r->gdi.dropTarget = NULL;
r->gdi.dropTarget = NULL;
r->gdi.drag_update = MwFALSE;
return r;
@ -1049,15 +1048,15 @@ static HRESULT STDMETHODCALLTYPE GDIDT_DragEnter(IDropTarget* this_, IDataObject
static HRESULT STDMETHODCALLTYPE GDIDT_DragOver(IDropTarget* this_, DWORD grfKeyState,
POINTL pt, DWORD* pdwEffect) {
MwLLGDIDropTarget* self = (MwLLGDIDropTarget*)this_;
MwLLGDIDropTarget* self = (MwLLGDIDropTarget*)this_;
self->handle->gdi.drag_update = MwTRUE;
return S_OK;
}
static HRESULT STDMETHODCALLTYPE GDIDT_DragLeave(IDropTarget* this_) {
MwLLGDIDropTarget* self = (MwLLGDIDropTarget*)this_;
self->handle->gdi.drag_update = MwFALSE;
MwLLGDIDropTarget* self = (MwLLGDIDropTarget*)this_;
self->handle->gdi.drag_update = MwFALSE;
return S_OK;
}
@ -1070,42 +1069,42 @@ static HRESULT STDMETHODCALLTYPE GDIDT_Drop(IDropTarget* this_, IDataObject* pDa
self->handle->gdi.drag_update = MwTRUE;
if(pDataObj->lpVtbl->GetData(pDataObj, &fmt, &stg) == S_OK) {
HDROP hDrop = (HDROP)stg.hGlobal;
UINT count = wsymtbl.DragQueryFileW(hDrop, 0xFFFFFFFF, NULL, 0);
UINT i, n;
HDROP hDrop = (HDROP)stg.hGlobal;
UINT count = wsymtbl.DragQueryFileW(hDrop, 0xFFFFFFFF, NULL, 0);
UINT i, n;
HRESULT hr;
for(i = 0; i < count; i++) {
wchar_t path[MAX_PATH];
char path_normal[MAX_PATH];
char *mime_type_normal;
wchar_t *mime_type = NULL;
int mime_type_size;
HRESULT hr;
int i;
wchar_t path[MAX_PATH];
char path_normal[MAX_PATH];
char* mime_type_normal;
wchar_t* mime_type = NULL;
int mime_type_size;
HRESULT hr;
int i;
wsymtbl.DragQueryFileW(hDrop, i, path, MAX_PATH);
wsymtbl.DragQueryFileA(hDrop, i, path_normal, MAX_PATH);
hr = wsymtbl.FindMimeFromData( NULL, path, NULL, 0,
NULL, FMFD_DEFAULT , &mime_type, 0x0 );
hr = wsymtbl.FindMimeFromData(NULL, path, NULL, 0,
NULL, FMFD_DEFAULT, &mime_type, 0x0);
mime_type_size = WideCharToMultiByte(CP_ACP, 0, mime_type, -1, NULL, 0, NULL, FALSE);
mime_type_size = WideCharToMultiByte(CP_ACP, 0, mime_type, -1, NULL, 0, NULL, FALSE);
mime_type_normal = malloc(sizeof(mime_type_size));
WideCharToMultiByte(CP_ACP, 0, mime_type, -1, mime_type_normal, mime_type_size, NULL, FALSE);
if(mime_type_size == 0) {
printf("Error converting mime type to multi-byte: %ld\n",GetLastError());
printf("Error converting mime type to multi-byte: %ld\n", GetLastError());
} else {
if(self->handle->common.known_mime_types) {
for(n = 0; n < arrlen(self->handle->common.known_mime_types); n++) {
if(strcmp(mime_type_normal, self->handle->common.known_mime_types[n]) == 0) {
MwDispatchUserHandler(self->handle->common.user, MwNdragAndDropHandler, path_normal);
break;
}
}
} else {
MwDispatchUserHandler(self->handle->common.user, MwNdragAndDropHandler, path_normal);
}
if(self->handle->common.known_mime_types) {
for(n = 0; n < arrlen(self->handle->common.known_mime_types); n++) {
if(strcmp(mime_type_normal, self->handle->common.known_mime_types[n]) == 0) {
MwDispatchUserHandler(self->handle->common.user, MwNdragAndDropHandler, path_normal);
break;
}
}
} else {
MwDispatchUserHandler(self->handle->common.user, MwNdragAndDropHandler, path_normal);
}
}
free(mime_type);
}
@ -1118,7 +1117,6 @@ static HRESULT STDMETHODCALLTYPE GDIDT_Drop(IDropTarget* this_, IDataObject* pDa
return S_OK;
}
static IDropTargetVtbl DropTarget_Vtbl = {
GDIDT_QueryInterface,
GDIDT_AddRef,
@ -1129,7 +1127,7 @@ static IDropTargetVtbl DropTarget_Vtbl = {
GDIDT_Drop};
static void MwLLSetupDragAndDropImpl(MwLL handle) {
HRESULT hr = 0;
HRESULT hr = 0;
handle->gdi.dropTarget = (MwLLGDIDropTarget*)malloc(sizeof(MwLLGDIDropTarget));
handle->gdi.dropTarget->lpVtbl = &DropTarget_Vtbl;
@ -1146,22 +1144,9 @@ static void MwLLSetupDragAndDropImpl(MwLL handle) {
}
static int MwLLGDICallInitImpl(void) {
void* ntdll;
void* ntdll;
HRESULT hr;
CoInitialize(NULL);
hr = OleInitialize(NULL);
if(!SUCCEEDED(hr)) {
if(hr == RPC_E_CHANGED_MODE) {
CoUninitialize();
hr = OleInitialize(NULL);
CoInitialize(NULL);
} else {
printf("OleInitialize failed; %08lx\n", hr);
return 1;
}
}
memset(&wsymtbl, 0, sizeof(wsymtbl));
wsymtbl.lib_dwmapi = MwDynamicOpen("dwmapi.dll");
@ -1174,24 +1159,69 @@ static int MwLLGDICallInitImpl(void) {
is_plgblt_reliable = 1;
}
wsymtbl.has_drag_and_drop = MwTRUE;
wsymtbl.has_drag_and_drop = MwFALSE;
if(!(wsymtbl.shell32lib = LoadLibrary("shell32.dll"))) {goto dnd_error;};
if(!(wsymtbl.ole32lib = LoadLibrary("ole32.dll"))) {goto dnd_error;};
if(!(wsymtbl.urlmonlib = LoadLibrary("Urlmon.dll"))) {goto dnd_error;};
/* Drag and Drop initialization */
{
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
/* The only other error - COM already being initialized - can be ignored */
if(hr == RPC_E_CHANGED_MODE) {
goto no_dnd;
}
if(!SUCCEEDED(hr) && hr != S_FALSE) {
printf("CoInitialize error: %08lx\n", hr);
goto dnd_error;
}
hr = OleInitialize(NULL);
if(!SUCCEEDED(hr)) {
if(hr == RPC_E_CHANGED_MODE) {
no_dnd:
printf("Cannot do drag and drop; Microsoft hates you and if you use COM anywhere else it has to be apartment threaded.\n");
goto dnd_error;
} else {
printf("OleInitialize failed; %08lx. Drag and Drop won't be supported.\n", hr);
goto dnd_error;
}
}
#define SHELL32_FUNC(x) if(!(wsymtbl.x = (void*)GetProcAddress(wsymtbl.shell32lib, #x))) {printf(#x "not found, drag and drop will not be supported"); goto dnd_error;}
#define OLE32_FUNC(x) if(!(wsymtbl.x = (void*)GetProcAddress(wsymtbl.ole32lib, #x))) {printf(#x "not found, drag and drop will not be supported"); goto dnd_error;}
#define URLMON_FUNC(x) if(!(wsymtbl.x = (void*)GetProcAddress(wsymtbl.urlmonlib, #x))) {printf(#x "not found, drag and drop will not be supported"); goto dnd_error;}
wsymtbl.has_drag_and_drop = MwTRUE;
SHELL32_FUNC(DragQueryFileW);
SHELL32_FUNC(DragQueryFileA);
OLE32_FUNC(ReleaseStgMedium);
OLE32_FUNC(RegisterDragDrop);
URLMON_FUNC(FindMimeFromData);
if(!(wsymtbl.shell32lib = LoadLibrary("shell32.dll"))) {
goto dnd_error;
};
if(!(wsymtbl.ole32lib = LoadLibrary("ole32.dll"))) {
goto dnd_error;
};
if(!(wsymtbl.urlmonlib = LoadLibrary("Urlmon.dll"))) {
goto dnd_error;
};
wsymtbl.has_drag_and_drop = MwTRUE;
#define SHELL32_FUNC(x) \
if(!(wsymtbl.x = (void*)GetProcAddress(wsymtbl.shell32lib, #x))) { \
printf(#x "not found, drag and drop will not be supported"); \
goto dnd_error; \
}
#define OLE32_FUNC(x) \
if(!(wsymtbl.x = (void*)GetProcAddress(wsymtbl.ole32lib, #x))) { \
printf(#x "not found, drag and drop will not be supported"); \
goto dnd_error; \
}
#define URLMON_FUNC(x) \
if(!(wsymtbl.x = (void*)GetProcAddress(wsymtbl.urlmonlib, #x))) { \
printf(#x "not found, drag and drop will not be supported"); \
goto dnd_error; \
}
SHELL32_FUNC(DragQueryFileW);
SHELL32_FUNC(DragQueryFileA);
OLE32_FUNC(ReleaseStgMedium);
OLE32_FUNC(RegisterDragDrop);
URLMON_FUNC(FindMimeFromData);
wsymtbl.has_drag_and_drop = MwTRUE;
}
dnd_error:
/* TODO: check properly */
return 0;
}