/********************************************************************** * FreeResource (KERNEL.63) * FreeResource16 (KERNEL32.@) */ BOOL16 WINAPI FreeResource16( HGLOBAL16 handle ) { HGLOBAL retv = handle; NE_MODULE *pModule = NE_GetPtr( FarGetOwner16( handle ) ); TRACE("(%04x)\n", handle ); /* Try NE resource first */ retv = NE_FreeResource( pModule, handle ); /* If this failed, call USER.DestroyIcon32; this will check whether it is a shared cursor/icon; if not it will call GlobalFree16() */ if ( retv ) { pDestroyIcon32Proc proc; HMODULE user = GetModuleHandleA( "user32.dll" ); if (user && (proc = (pDestroyIcon32Proc)GetProcAddress( user, "DestroyIcon32" ))) retv = proc( handle, CID_RESOURCE ); else retv = GlobalFree16( handle ); } return (BOOL)retv; }
/*********************************************************************** * SetWindowsHook (USER.121) */ FARPROC16 WINAPI SetWindowsHook16( INT16 id, HOOKPROC16 proc ) { HINSTANCE16 hInst = FarGetOwner16( HIWORD(proc) ); /* WH_MSGFILTER is the only task-specific hook for SetWindowsHook() */ HTASK16 hTask = (id == WH_MSGFILTER) ? GetCurrentTask() : 0; return (FARPROC16)SetWindowsHookEx16( id, proc, hInst, hTask ); }
/*********************************************************************** * MakeProcInstance (KERNEL.51) */ FARPROC16 WINAPI MakeProcInstance16( FARPROC16 func, HANDLE16 hInstance ) { struct thunk *thunk; BYTE *lfunc; SEGPTR thunkaddr; WORD hInstanceSelector; hInstanceSelector = GlobalHandleToSel16(hInstance); TRACE("(%p, %04x);\n", func, hInstance); if (!HIWORD(func)) { /* Win95 actually protects via SEH, but this is better for debugging */ WARN("Ouch ! Called with invalid func %p !\n", func); return NULL; } if ( (GlobalHandleToSel16(CURRENT_DS) != hInstanceSelector) && (hInstance != 0) && (hInstance != 0xffff) ) { /* calling MPI with a foreign DSEG is invalid ! */ WARN("Problem with hInstance? Got %04x, using %04x instead\n", hInstance,CURRENT_DS); } /* Always use the DSEG that MPI was entered with. * We used to set hInstance to GetTaskDS16(), but this should be wrong * as CURRENT_DS provides the DSEG value we need. * ("calling" DS, *not* "task" DS !) */ hInstanceSelector = CURRENT_DS; hInstance = GlobalHandle16(hInstanceSelector); /* no thunking for DLLs */ if (NE_GetPtr(FarGetOwner16(hInstance))->ne_flags & NE_FFLAGS_LIBMODULE) return func; thunkaddr = TASK_AllocThunk(); if (!thunkaddr) return NULL; thunk = MapSL( thunkaddr ); lfunc = MapSL( (SEGPTR)func ); TRACE("(%p,%04x): got thunk %08x\n", func, hInstance, thunkaddr ); if (((lfunc[0]==0x8c) && (lfunc[1]==0xd8)) || /* movw %ds, %ax */ ((lfunc[0]==0x1e) && (lfunc[1]==0x58)) /* pushw %ds, popw %ax */ ) { WARN("This was the (in)famous \"thunk useless\" warning. We thought we have to overwrite with nop;nop;, but this isn't true.\n"); } thunk->movw = 0xb8; /* movw instance, %ax */ thunk->instance = hInstanceSelector; thunk->ljmp = 0xea; /* ljmp func */ thunk->func = func; return (FARPROC16)thunkaddr; /* CX reg indicates if thunkaddr != NULL, implement if needed */ }
/********************************************************************** * FreeResource (KERNEL.63) */ BOOL16 WINAPI FreeResource16( HGLOBAL16 handle ) { FARPROC16 proc; HMODULE16 user; NE_MODULE *pModule = NE_GetPtr( FarGetOwner16( handle ) ); TRACE("(%04x)\n", handle ); /* Try NE resource first */ if (pModule && pModule->ne_rsrctab) { NE_TYPEINFO *pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->ne_rsrctab + 2); while (pTypeInfo->type_id) { WORD count; NE_NAMEINFO *pNameInfo = (NE_NAMEINFO *)(pTypeInfo + 1); for (count = pTypeInfo->count; count > 0; count--) { if (pNameInfo->handle == handle) { if (pNameInfo->usage > 0) pNameInfo->usage--; if (pNameInfo->usage == 0) { GlobalFree16( pNameInfo->handle ); pNameInfo->handle = 0; pNameInfo->flags &= ~NE_SEGFLAGS_LOADED; } return FALSE; } pNameInfo++; } pTypeInfo = (NE_TYPEINFO *)pNameInfo; } } /* If this failed, call USER.DestroyIcon32; this will check whether it is a shared cursor/icon; if not it will call GlobalFree16() */ user = GetModuleHandle16( "user" ); if (user && (proc = GetProcAddress16( user, "DestroyIcon32" ))) { WORD args[2]; DWORD result; args[1] = handle; args[0] = 1; /* CID_RESOURCE */ WOWCallback16Ex( (SEGPTR)proc, WCB16_PASCAL, sizeof(args), args, &result ); return LOWORD(result); } else return GlobalFree16( handle ); }
/*********************************************************************** * get_entry_point * * Return the ordinal, name, and type info corresponding to a CS:IP address. */ static const CALLFROM16 *get_entry_point( STACK16FRAME *frame, LPSTR module, LPSTR func, WORD *pOrd ) { WORD i, max_offset; register BYTE *p; NE_MODULE *pModule; ET_BUNDLE *bundle; ET_ENTRY *entry; *pOrd = 0; if (!(pModule = NE_GetPtr( FarGetOwner16( GlobalHandle16( frame->module_cs ) )))) return NULL; max_offset = 0; bundle = (ET_BUNDLE *)((BYTE *)pModule + pModule->ne_enttab); do { entry = (ET_ENTRY *)((BYTE *)bundle+6); for (i = bundle->first + 1; i <= bundle->last; i++) { if ((entry->offs < frame->entry_ip) && (entry->segnum == 1) /* code segment ? */ && (entry->offs >= max_offset)) { max_offset = entry->offs; *pOrd = i; } entry++; } } while ( (bundle->next) && (bundle = (ET_BUNDLE *)((BYTE *)pModule+bundle->next))); /* Search for the name in the resident names table */ /* (built-in modules have no non-resident table) */ p = (BYTE *)pModule + pModule->ne_restab; memcpy( module, p + 1, *p ); module[*p] = 0; while (*p) { p += *p + 1 + sizeof(WORD); if (*(WORD *)(p + *p + 1) == *pOrd) break; } memcpy( func, p + 1, *p ); func[*p] = 0; /* Retrieve entry point call structure */ p = MapSL( MAKESEGPTR( frame->module_cs, frame->callfrom_ip ) ); /* p now points to lret, get the start of CALLFROM16 structure */ return (CALLFROM16 *)(p - FIELD_OFFSET( CALLFROM16, ret )); }
/********************************************************************** * FreeResource (KERNEL.63) */ BOOL16 WINAPI FreeResource16( HGLOBAL16 handle ) { pDestroyIcon32Proc proc; HMODULE user; NE_MODULE *pModule = NE_GetPtr( FarGetOwner16( handle ) ); TRACE("(%04x)\n", handle ); /* Try NE resource first */ if (pModule && pModule->ne_rsrctab) { NE_TYPEINFO *pTypeInfo = (NE_TYPEINFO *)((char *)pModule + pModule->ne_rsrctab + 2); while (pTypeInfo->type_id) { WORD count; NE_NAMEINFO *pNameInfo = (NE_NAMEINFO *)(pTypeInfo + 1); for (count = pTypeInfo->count; count > 0; count--) { if (pNameInfo->handle == handle) { if (pNameInfo->usage > 0) pNameInfo->usage--; if (pNameInfo->usage == 0) { GlobalFree16( pNameInfo->handle ); pNameInfo->handle = 0; pNameInfo->flags &= ~NE_SEGFLAGS_LOADED; } return 0; } pNameInfo++; } pTypeInfo = (NE_TYPEINFO *)pNameInfo; } } /* If this failed, call USER.DestroyIcon32; this will check whether it is a shared cursor/icon; if not it will call GlobalFree16() */ user = GetModuleHandleA( "user32.dll" ); if (user && (proc = (pDestroyIcon32Proc)GetProcAddress( user, "DestroyIcon32" ))) return proc( handle, 1 /*CID_RESOURCE*/ ); else return GlobalFree16( handle ); }
/*********************************************************************** * GetExePtrHelper */ static inline HMODULE16 GetExePtrHelper( HANDLE16 handle, HTASK16 *hTask ) { char *ptr; HANDLE16 owner; /* Check for module handle */ if (!(ptr = GlobalLock16( handle ))) return 0; if (((NE_MODULE *)ptr)->ne_magic == IMAGE_OS2_SIGNATURE) return handle; /* Search for this handle inside all tasks */ *hTask = hFirstTask; while (*hTask) { TDB *pTask = TASK_GetPtr( *hTask ); if ((*hTask == handle) || (pTask->hInstance == handle) || (pTask->hQueue == handle) || (pTask->hPDB == handle)) return pTask->hModule; *hTask = pTask->hNext; } /* Check the owner for module handle */ owner = FarGetOwner16( handle ); if (!(ptr = GlobalLock16( owner ))) return 0; if (((NE_MODULE *)ptr)->ne_magic == IMAGE_OS2_SIGNATURE) return owner; /* Search for the owner inside all tasks */ *hTask = hFirstTask; while (*hTask) { TDB *pTask = TASK_GetPtr( *hTask ); if ((*hTask == owner) || (pTask->hInstance == owner) || (pTask->hQueue == owner) || (pTask->hPDB == owner)) return pTask->hModule; *hTask = pTask->hNext; } return 0; }
/*********************************************************************** * PatchCodeHandle (KERNEL.110) * * Needed for self-loading modules. */ DWORD WINAPI PatchCodeHandle16(HANDLE16 hSeg) { WORD segnum; WORD sel = SEL(hSeg); NE_MODULE *pModule = NE_GetPtr(FarGetOwner16(sel)); SEGTABLEENTRY *pSegTable = NE_SEG_TABLE(pModule); TRACE_(module)("(%04x);\n", hSeg); /* find the segment number of the module that belongs to hSeg */ for (segnum = 1; segnum <= pModule->ne_cseg; segnum++) { if (SEL(pSegTable[segnum-1].hSeg) == sel) { NE_FixupSegmentPrologs(pModule, segnum); break; } } return MAKELONG(hSeg, sel); }