int ps_get_monitor_timing(int monitor_index, MonitorTiming *timing) { LRESULT lresult; char in[256]; if (!hPSWnd) return 0; lresult = SendMessage(hPSWnd, UM_GETTIMING, monitor_index, 0); if (lresult == -1) { mame_printf_verbose("PStrip: Could not get PowerStrip timing string\n"); return 0; } if (!GlobalGetAtomNameA(lresult, in, sizeof(in))) { mame_printf_verbose("PStrip: GlobalGetAtomName failed\n"); return 0; } mame_printf_verbose("PStrip: ps_get_monitor_timing(%d): %s\n", monitor_index, in); read_timing_string(in, timing); GlobalDeleteAtom(lresult); // delete atom created by PowerStrip return 1; }
/***************************************************************************** * WMHOTKEYPROC: event callback *****************************************************************************/ LRESULT CALLBACK WMHOTKEYPROC( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch( uMsg ) { case WM_HOTKEY: { int i; char psz_atomName[40]; intf_thread_t *p_intf = (intf_thread_t*)GetWindowLongPtr( hwnd, GWL_USERDATA ); struct hotkey *p_hotkeys = p_intf->p_libvlc->p_hotkeys; i = GlobalGetAtomNameA( wParam, psz_atomName, sizeof( psz_atomName ) ); if( !i ) return 0; /* search for key associated with VLC */ for( i = 0; p_hotkeys[i].psz_action != NULL; i++ ) { if( strcmp( p_hotkeys[i].psz_action, psz_atomName ) ) continue; var_SetInteger( p_intf->p_libvlc, "key-action", p_hotkeys[i].i_action ); return 1; } } break; case WM_DESTROY: PostQuitMessage( 0 ); break; default: return DefWindowProc( hwnd, uMsg, wParam, lParam ); } return 0; }
/***************************************************************************** * WMHOTKEYPROC: event callback *****************************************************************************/ LRESULT CALLBACK WMHOTKEYPROC( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch( uMsg ) { case WM_HOTKEY: { char psz_atomName[44]; LONG_PTR ret = GetWindowLongPtr( hwnd, GWLP_USERDATA ); intf_thread_t *p_intf = (intf_thread_t*)ret; strcpy( psz_atomName, "key-" ); if( !GlobalGetAtomNameA( wParam, psz_atomName + 4, sizeof( psz_atomName ) - 4 ) ) return 0; /* search for key associated with VLC */ vlc_action_t action = vlc_GetActionId( psz_atomName ); if( action != ACTIONID_NONE ) { var_SetInteger( p_intf->obj.libvlc, "key-action", action ); return 1; } } break; case WM_DESTROY: PostQuitMessage( 0 ); break; default: return DefWindowProc( hwnd, uMsg, wParam, lParam ); } return 0; }
static BOOL get_display_device_reg_key(char *key, unsigned len) { static const char display_device_guid_prop[] = "__wine_display_device_guid"; static const char video_path[] = "System\\CurrentControlSet\\Control\\Video\\{"; static const char display0[] = "}\\0000"; ATOM guid_atom; assert(len >= sizeof(video_path) + sizeof(display0) + 40); guid_atom = HandleToULong(GetPropA(GetDesktopWindow(), display_device_guid_prop)); if (!guid_atom) return FALSE; memcpy(key, video_path, sizeof(video_path)); if (!GlobalGetAtomNameA(guid_atom, key + strlen(key), 40)) return FALSE; strcat(key, display0); TRACE("display device key %s\n", wine_dbgstr_a(key)); return TRUE; }
static void test_handles(void) { HWINSTA w1, w2, w3; HDESK d1, d2, d3; HANDLE hthread; DWORD id, flags, le; ATOM atom; char buffer[20]; /* win stations */ w1 = GetProcessWindowStation(); ok( GetProcessWindowStation() == w1, "GetProcessWindowStation returned different handles\n" ); ok( !CloseWindowStation(w1), "closing process win station succeeded\n" ); SetLastError( 0xdeadbeef ); ok( !CloseHandle(w1), "closing process win station handle succeeded\n" ); ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %d\n", GetLastError() ); print_object( w1 ); flags = 0; ok( GetHandleInformation( w1, &flags ), "GetHandleInformation failed\n" ); ok( !(flags & HANDLE_FLAG_PROTECT_FROM_CLOSE) || broken(flags & HANDLE_FLAG_PROTECT_FROM_CLOSE), /* set on nt4 */ "handle %p PROTECT_FROM_CLOSE set\n", w1 ); ok( DuplicateHandle( GetCurrentProcess(), w1, GetCurrentProcess(), (PHANDLE)&w2, 0, TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" ); ok( CloseWindowStation(w2), "closing dup win station failed\n" ); ok( DuplicateHandle( GetCurrentProcess(), w1, GetCurrentProcess(), (PHANDLE)&w2, 0, TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" ); ok( CloseHandle(w2), "closing dup win station handle failed\n" ); w2 = CreateWindowStation("WinSta0", 0, WINSTA_ALL_ACCESS, NULL ); le = GetLastError(); ok( w2 != 0 || le == ERROR_ACCESS_DENIED, "CreateWindowStation failed (%u)\n", le ); if (w2 != 0) { ok( w2 != w1, "CreateWindowStation returned default handle\n" ); SetLastError( 0xdeadbeef ); ok( !CloseDesktop( (HDESK)w2 ), "CloseDesktop succeeded on win station\n" ); ok( GetLastError() == ERROR_INVALID_HANDLE || broken(GetLastError() == 0xdeadbeef), /* wow64 */ "bad last error %d\n", GetLastError() ); ok( CloseWindowStation( w2 ), "CloseWindowStation failed\n" ); w2 = CreateWindowStation("WinSta0", 0, WINSTA_ALL_ACCESS, NULL ); ok( CloseHandle( w2 ), "CloseHandle failed\n" ); } else if (le == ERROR_ACCESS_DENIED) win_skip( "Not enough privileges for CreateWindowStation\n" ); w2 = OpenWindowStation("winsta0", TRUE, WINSTA_ALL_ACCESS ); ok( w2 != 0, "OpenWindowStation failed\n" ); ok( w2 != w1, "OpenWindowStation returned default handle\n" ); ok( CloseWindowStation( w2 ), "CloseWindowStation failed\n" ); w2 = OpenWindowStation("dummy name", TRUE, WINSTA_ALL_ACCESS ); ok( !w2, "open dummy win station succeeded\n" ); CreateMutexA( NULL, 0, "foobar" ); w2 = CreateWindowStation("foobar", 0, WINSTA_ALL_ACCESS, NULL ); le = GetLastError(); ok( w2 != 0 || le == ERROR_ACCESS_DENIED, "create foobar station failed (%u)\n", le ); if (w2 != 0) { w3 = OpenWindowStation("foobar", TRUE, WINSTA_ALL_ACCESS ); ok( w3 != 0, "open foobar station failed\n" ); ok( w3 != w2, "open foobar station returned same handle\n" ); ok( CloseWindowStation( w2 ), "CloseWindowStation failed\n" ); ok( CloseWindowStation( w3 ), "CloseWindowStation failed\n" ); w3 = OpenWindowStation("foobar", TRUE, WINSTA_ALL_ACCESS ); ok( !w3, "open foobar station succeeded\n" ); w2 = CreateWindowStation("foobar1", 0, WINSTA_ALL_ACCESS, NULL ); ok( w2 != 0, "create foobar station failed\n" ); w3 = CreateWindowStation("foobar2", 0, WINSTA_ALL_ACCESS, NULL ); ok( w3 != 0, "create foobar station failed\n" ); ok( GetHandleInformation( w2, &flags ), "GetHandleInformation failed\n" ); ok( GetHandleInformation( w3, &flags ), "GetHandleInformation failed\n" ); SetProcessWindowStation( w2 ); atom = GlobalAddAtomA("foo"); ok( GlobalGetAtomNameA( atom, buffer, sizeof(buffer) ) == 3, "GlobalGetAtomName failed\n" ); ok( !lstrcmpiA( buffer, "foo" ), "bad atom value %s\n", buffer ); ok( !CloseWindowStation( w2 ), "CloseWindowStation succeeded\n" ); ok( GetHandleInformation( w2, &flags ), "GetHandleInformation failed\n" ); SetProcessWindowStation( w3 ); ok( GetHandleInformation( w2, &flags ), "GetHandleInformation failed\n" ); ok( CloseWindowStation( w2 ), "CloseWindowStation failed\n" ); ok( GlobalGetAtomNameA( atom, buffer, sizeof(buffer) ) == 3, "GlobalGetAtomName failed\n" ); ok( !lstrcmpiA( buffer, "foo" ), "bad atom value %s\n", buffer ); } else if (le == ERROR_ACCESS_DENIED) win_skip( "Not enough privileges for CreateWindowStation\n" ); /* desktops */ d1 = GetThreadDesktop(GetCurrentThreadId()); initial_desktop = d1; ok( GetThreadDesktop(GetCurrentThreadId()) == d1, "GetThreadDesktop returned different handles\n" ); flags = 0; ok( GetHandleInformation( d1, &flags ), "GetHandleInformation failed\n" ); ok( !(flags & HANDLE_FLAG_PROTECT_FROM_CLOSE), "handle %p PROTECT_FROM_CLOSE set\n", d1 ); SetLastError( 0xdeadbeef ); ok( !CloseDesktop(d1), "closing thread desktop succeeded\n" ); ok( GetLastError() == ERROR_BUSY || broken(GetLastError() == 0xdeadbeef), /* wow64 */ "bad last error %d\n", GetLastError() ); SetLastError( 0xdeadbeef ); if (CloseHandle( d1 )) /* succeeds on nt4 */ { win_skip( "NT4 desktop handle management is completely different\n" ); return; } ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %d\n", GetLastError() ); ok( DuplicateHandle( GetCurrentProcess(), d1, GetCurrentProcess(), (PHANDLE)&d2, 0, TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" ); ok( CloseDesktop(d2), "closing dup desktop failed\n" ); ok( DuplicateHandle( GetCurrentProcess(), d1, GetCurrentProcess(), (PHANDLE)&d2, 0, TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" ); ok( CloseHandle(d2), "closing dup desktop handle failed\n" ); d2 = OpenDesktop( "dummy name", 0, TRUE, DESKTOP_ALL_ACCESS ); ok( !d2, "open dummy desktop succeeded\n" ); d2 = CreateDesktop( "foobar", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL ); ok( d2 != 0, "create foobar desktop failed\n" ); SetLastError( 0xdeadbeef ); ok( !CloseWindowStation( (HWINSTA)d2 ), "CloseWindowStation succeeded on desktop\n" ); ok( GetLastError() == ERROR_INVALID_HANDLE || broken(GetLastError() == 0xdeadbeef), /* wow64 */ "bad last error %d\n", GetLastError() ); SetLastError( 0xdeadbeef ); d3 = CreateDesktop( "foobar", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL ); ok( d3 != 0, "create foobar desktop again failed\n" ); ok( GetLastError() == 0xdeadbeef, "bad last error %d\n", GetLastError() ); ok( CloseDesktop( d3 ), "CloseDesktop failed\n" ); d3 = OpenDesktop( "foobar", 0, TRUE, DESKTOP_ALL_ACCESS ); ok( d3 != 0, "open foobar desktop failed\n" ); ok( d3 != d2, "open foobar desktop returned same handle\n" ); ok( CloseDesktop( d2 ), "CloseDesktop failed\n" ); ok( CloseDesktop( d3 ), "CloseDesktop failed\n" ); d3 = OpenDesktop( "foobar", 0, TRUE, DESKTOP_ALL_ACCESS ); ok( !d3, "open foobar desktop succeeded\n" ); ok( !CloseHandle(d1), "closing thread desktop handle succeeded\n" ); d2 = GetThreadDesktop(GetCurrentThreadId()); ok( d1 == d2, "got different handles after close\n" ); register_class(); trace( "thread 1 desktop: %p\n", d1 ); print_object( d1 ); hthread = CreateThread( NULL, 0, thread, (LPVOID)2, 0, &id ); Sleep(1000); trace( "get other thread desktop: %p\n", GetThreadDesktop(id) ); WaitForSingleObject( hthread, INFINITE ); CloseHandle( hthread ); }
static void test_get_atom_name(void) { char buf[10]; WCHAR bufW[10]; int i; UINT len; static const WCHAR resultW[] = {'f','o','o','b','a','r',0,'.','.','.'}; char in[257], out[257]; WCHAR inW[257], outW[257]; ATOM atom = GlobalAddAtomA( "foobar" ); /* Get the name of the atom we added above */ memset( buf, '.', sizeof(buf) ); len = GlobalGetAtomNameA( atom, buf, 10 ); ok( len == strlen("foobar"), "bad length %d\n", len ); ok( !memcmp( buf, "foobar\0...", 10 ), "bad buffer contents\n" ); /* Repeat, unicode-style */ if (unicode_OS) { for (i = 0; i < 10; i++) bufW[i] = '.'; SetLastError( 0xdeadbeef ); len = GlobalGetAtomNameW( atom, bufW, 10 ); ok( len && GetLastError() == 0xdeadbeef, "GlobalGetAtomNameW failed\n" ); ok( len == lstrlenW(foobarW), "bad length %d\n", len ); ok( !memcmp( bufW, resultW, 10*sizeof(WCHAR) ), "bad buffer contents\n" ); } /* Check error code returns */ memset(buf, '.', 10); ok( !GlobalGetAtomNameA( atom, buf, 0 ), "succeeded\n" ); ok( !memcmp( buf, "..........", 10 ), "should not touch buffer\n" ); if (unicode_OS) { static const WCHAR sampleW[] = {'.','.','.','.','.','.','.','.','.','.'}; for (i = 0; i < 10; i++) bufW[i] = '.'; ok( !GlobalGetAtomNameW( atom, bufW, 0 ), "succeeded\n" ); ok( !memcmp( bufW, sampleW, sizeof(sampleW) ), "should not touch buffer\n" ); } /* Test integer atoms */ for (i = 0; i <= 0xbfff; i++) { memset( buf, 'a', 10 ); len = GlobalGetAtomNameA( (ATOM)i, buf, 10 ); if (i) { char res[20]; ok( (len > 1) && (len < 7), "bad length %d\n", len ); sprintf( res, "#%d", i ); memset( res + strlen(res) + 1, 'a', 10 ); ok( !memcmp( res, buf, 10 ), "bad buffer contents %s\n", buf ); if (len <= 1 || len >= 7) break; /* don't bother testing all of them */ } else ok( !len, "bad length %d\n", len ); SetLastError(0xdeadbeef); len = GlobalGetAtomNameA( (ATOM)i, buf, 2); ok(!len, "bad length %d\n", len); ok(GetLastError() == ERROR_MORE_DATA || GetLastError() == ERROR_INVALID_PARAMETER, "wrong error conditions %u for %u\n", GetLastError(), i); } memset( buf, '.', sizeof(buf) ); len = GlobalGetAtomNameA( atom, buf, 6 ); ok( len == 0, "bad length %d\n", len ); ok( !memcmp( buf, "fooba\0....", 10 ), "bad buffer contents\n"); if (unicode_OS) { static const WCHAR resW[] = {'f','o','o','b','a','r','.','.','.','.'}; for (len = 0; len < 10; len++) bufW[len] = '.'; SetLastError(0xdeadbeef); len = GlobalGetAtomNameW( atom, bufW, 6 ); ok( len && GetLastError() == 0xdeadbeef, "GlobalGetAtomNameW failed\n" ); ok( len == lstrlenW(foobarW), "bad length %d\n", len ); ok( !memcmp( bufW, resW, 10*sizeof(WCHAR) ), "bad buffer contents\n" ); } /* test string limits & overflow */ do_initA(in, "abcdefghij", 255); atom = GlobalAddAtomA(in); ok(atom, "couldn't add atom for %s\n", in); len = GlobalGetAtomNameA(atom, out, sizeof(out)); ok(len == 255, "length mismatch (%u instead of 255)\n", len); for (i = 0; i < 255; i++) { ok(out[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, out[i], "abcdefghij"[i % 10]); } ok(out[255] == '\0', "wrong end of string\n"); memset(out, '.', sizeof(out)); SetLastError(0xdeadbeef); len = GlobalGetAtomNameA(atom, out, 10); ok(!len, "bad length %d\n", len); ok(GetLastError() == ERROR_MORE_DATA, "wrong error code (%u instead of %u)\n", GetLastError(), ERROR_MORE_DATA); for (i = 0; i < 9; i++) { ok(out[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, out[i], "abcdefghij"[i % 10]); } ok(out[9] == '\0', "wrong end of string\n"); ok(out[10] == '.', "wrote after end of buf\n"); do_initA(in, "abcdefghij", 256); atom = GlobalAddAtomA(in); ok(!atom, "succeeded\n"); if (unicode_OS) { /* test integral atoms */ for (i = 0; i <= 0xbfff; i++) { memset(outW, 'a', sizeof(outW)); len = GlobalGetAtomNameW( (ATOM)i, outW, 10 ); if (i) { WCHAR res[20]; ok( (len > 1) && (len < 7), "bad length %d\n", len ); wsprintfW( res, integfmt, i ); memset( res + lstrlenW(res) + 1, 'a', 10 * sizeof(WCHAR)); ok( !memcmp( res, outW, 10 * sizeof(WCHAR) ), "bad buffer contents for %d\n", i ); if (len <= 1 || len >= 7) break; /* don't bother testing all of them */ } else ok( !len, "bad length %d\n", len ); memset(outW, '.', sizeof(outW)); SetLastError(0xdeadbeef); len = GlobalGetAtomNameW( (ATOM)i, outW, 1); if (i) { /* len == 0 with ERROR_MORE_DATA is on NT3.51 */ ok(len == 1 || (len == 0 && GetLastError() == ERROR_MORE_DATA), "0x%04x: got %u with %d (expected '1' or '0' with " "ERROR_MORE_DATA)\n", i, len, GetLastError()); ok(outW[1] == DOUBLE('.'), "buffer overwrite\n"); } else ok(len == 0 && GetLastError() == ERROR_INVALID_PARAMETER, "0 badly handled\n"); } do_initW(inW, "abcdefghij", 255); atom = GlobalAddAtomW(inW); ok(atom, "couldn't add atom for %s\n", in); len = GlobalGetAtomNameW(atom, outW, sizeof(outW)/sizeof(outW[0])); ok(len == 255, "length mismatch (%u instead of 255)\n", len); for (i = 0; i < 255; i++) { ok(outW[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, outW[i], "abcdefghij"[i % 10]); } ok(outW[255] == '\0', "wrong end of string\n"); memset(outW, '.', sizeof(outW)); len = GlobalGetAtomNameW(atom, outW, 10); ok(len == 10, "succeeded\n"); for (i = 0; i < 10; i++) { ok(outW[i] == "abcdefghij"[i % 10], "wrong string at %i (%c instead of %c)\n", i, outW[i], "abcdefghij"[i % 10]); } ok(outW[10] == DOUBLE('.'), "wrote after end of buf\n"); do_initW(inW, "abcdefghij", 256); atom = GlobalAddAtomW(inW); ok(!atom, "succeeded\n"); ok(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error code\n"); } }
/* * @implemented */ int WINAPI EnumPropsA(HWND hWnd, PROPENUMPROCA lpEnumFunc) { PPROPLISTITEM pli, i; NTSTATUS Status; DWORD Count; int ret = -1; if(!lpEnumFunc) { SetLastError(ERROR_INVALID_PARAMETER); return ret; } Status = NtUserBuildPropList(hWnd, NULL, 0, &Count); if(!NT_SUCCESS(Status)) { if(Status == STATUS_INVALID_HANDLE) SetLastError(ERROR_INVALID_WINDOW_HANDLE); else SetLastError(RtlNtStatusToDosError(Status)); return ret; } if(Count > 0) { pli = RtlAllocateHeap(GetProcessHeap(), 0, Count); if (pli == NULL) { SetLastError(ERROR_OUTOFMEMORY); return -1; } Status = NtUserBuildPropList(hWnd, (LPVOID)pli, Count, &Count); if(!NT_SUCCESS(Status)) { RtlFreeHeap(GetProcessHeap(), 0, pli); if(Status == STATUS_INVALID_HANDLE) SetLastError(ERROR_INVALID_WINDOW_HANDLE); else SetLastError(RtlNtStatusToDosError(Status)); return ret; } i = pli; for(; Count > 0; Count--, i++) { char str[ATOM_BUFFER_SIZE]; if(!GlobalGetAtomNameA(i->Atom, str, ATOM_BUFFER_SIZE)) continue; ret = lpEnumFunc(hWnd, str, i->Data); if(!ret) break; } RtlFreeHeap(GetProcessHeap(), 0, pli); } return ret; }
void WINAPI VXD_Win32s( CONTEXT86 *context ) { switch (AX_reg(context)) { case 0x0000: /* Get Version */ /* * Input: None * * Output: EAX: LoWord: Win32s Version (1.30) * HiWord: VxD Version (200) * * EBX: Build (172) * * ECX: ??? (1) * * EDX: Debugging Flags * * EDI: Error Flag * 0 if OK, * 1 if VMCPD VxD not found */ TRACE("GetVersion()\n"); context->Eax = VXD_WinVersion() | (200 << 16); context->Ebx = 0; context->Ecx = 0; context->Edx = 0; context->Edi = 0; /* * If this is the first time we are called for this process, * hack the memory image of WIN32S16 so that it doesn't try * to access the GDT directly ... * * The first code segment of WIN32S16 (version 1.30) contains * an unexported function somewhere between the exported functions * SetFS and StackLinearToSegmented that tries to find a selector * in the LDT that maps to the memory image of the LDT itself. * If it succeeds, it stores this selector into a global variable * which will be used to speed up execution by using this selector * to modify the LDT directly instead of using the DPMI calls. * * To perform this search of the LDT, this function uses the * sgdt and sldt instructions to find the linear address of * the (GDT and then) LDT. While those instructions themselves * execute without problem, the linear address that sgdt returns * points (at least under Linux) to the kernel address space, so * that any subsequent access leads to a segfault. * * Fortunately, WIN32S16 still contains as a fallback option the * mechanism of using DPMI calls to modify LDT selectors instead * of direct writes to the LDT. Thus we can circumvent the problem * by simply replacing the first byte of the offending function * with an 'retf' instruction. This means that the global variable * supposed to contain the LDT alias selector will remain zero, * and hence WIN32S16 will fall back to using DPMI calls. * * The heuristic we employ to _find_ that function is as follows: * We search between the addresses of the exported symbols SetFS * and StackLinearToSegmented for the byte sequence '0F 01 04' * (this is the opcode of 'sgdt [si]'). We then search backwards * from this address for the last occurrence of 'CB' (retf) that marks * the end of the preceeding function. The following byte (which * should now be the first byte of the function we are looking for) * will be replaced by 'CB' (retf). * * This heuristic works for the retail as well as the debug version * of Win32s version 1.30. For versions earlier than that this * hack should not be necessary at all, since the whole mechanism * ('PERF130') was introduced only in 1.30 to improve the overall * performance of Win32s. */ if (!W32S_offset) { HMODULE16 hModule = GetModuleHandle16("win32s16"); SEGPTR func1 = (SEGPTR)GetProcAddress16(hModule, "SetFS"); SEGPTR func2 = (SEGPTR)GetProcAddress16(hModule, "StackLinearToSegmented"); if ( hModule && func1 && func2 && SELECTOROF(func1) == SELECTOROF(func2)) { BYTE *start = MapSL(func1); BYTE *end = MapSL(func2); BYTE *p, *retv = NULL; int found = 0; for (p = start; p < end; p++) if (*p == 0xCB) found = 0, retv = p; else if (*p == 0x0F) found = 1; else if (*p == 0x01 && found == 1) found = 2; else if (*p == 0x04 && found == 2) { found = 3; break; } else found = 0; if (found == 3 && retv) { TRACE("PERF130 hack: " "Replacing byte %02X at offset %04X:%04X\n", *(retv+1), SELECTOROF(func1), OFFSETOF(func1) + retv+1-start); *(retv+1) = (BYTE)0xCB; } } } /* * Mark process as Win32s, so that subsequent DPMI calls * will perform the W32S_APP2WINE/W32S_WINE2APP address shift. */ W32S_offset = 0x10000; break; case 0x0001: /* Install Exception Handling */ /* * Input: EBX: Flat address of W32SKRNL Exception Data * * ECX: LoWord: Flat Code Selector * HiWord: Flat Data Selector * * EDX: Flat address of W32SKRNL Exception Handler * (this is equal to W32S_BackTo32 + 0x40) * * ESI: SEGPTR KERNEL.HASGPHANDLER * * EDI: SEGPTR phCurrentTask (KERNEL.THHOOK + 0x10) * * Output: EAX: 0 if OK */ TRACE("[0001] EBX=%lx ECX=%lx EDX=%lx ESI=%lx EDI=%lx\n", context->Ebx, context->Ecx, context->Edx, context->Esi, context->Edi); /* FIXME */ context->Eax = 0; break; case 0x0002: /* Set Page Access Flags */ /* * Input: EBX: New access flags * Bit 2: User Page if set, Supervisor Page if clear * Bit 1: Read-Write if set, Read-Only if clear * * ECX: Size of memory area to change * * EDX: Flat start address of memory area * * Output: EAX: Size of area changed */ TRACE("[0002] EBX=%lx ECX=%lx EDX=%lx\n", context->Ebx, context->Ecx, context->Edx); /* FIXME */ context->Eax = context->Ecx; break; case 0x0003: /* Get Page Access Flags */ /* * Input: EDX: Flat address of page to query * * Output: EAX: Page access flags * Bit 2: User Page if set, Supervisor Page if clear * Bit 1: Read-Write if set, Read-Only if clear */ TRACE("[0003] EDX=%lx\n", context->Edx); /* FIXME */ context->Eax = 6; break; case 0x0004: /* Map Module */ /* * Input: ECX: IMTE (offset in Module Table) of new module * * EDX: Flat address of Win32s Module Table * * Output: EAX: 0 if OK */ if (!context->Edx || CX_reg(context) == 0xFFFF) { TRACE("MapModule: Initialization call\n"); context->Eax = 0; } else { /* * Structure of a Win32s Module Table Entry: */ struct Win32sModule { DWORD flags; DWORD flatBaseAddr; LPCSTR moduleName; LPCSTR pathName; LPCSTR unknown; LPBYTE baseAddr; DWORD hModule; DWORD relocDelta; }; /* * Note: This function should set up a demand-paged memory image * of the given module. Since mmap does not allow file offsets * not aligned at 1024 bytes, we simply load the image fully * into memory. */ struct Win32sModule *moduleTable = (struct Win32sModule *)W32S_APP2WINE(context->Edx); struct Win32sModule *module = moduleTable + context->Ecx; IMAGE_NT_HEADERS *nt_header = PE_HEADER(module->baseAddr); IMAGE_SECTION_HEADER *pe_seg = PE_SECTIONS(module->baseAddr); HFILE image = _lopen(module->pathName, OF_READ); BOOL error = (image == HFILE_ERROR); UINT i; TRACE("MapModule: Loading %s\n", module->pathName); for (i = 0; !error && i < nt_header->FileHeader.NumberOfSections; i++, pe_seg++) if(!(pe_seg->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)) { DWORD off = pe_seg->PointerToRawData; DWORD len = pe_seg->SizeOfRawData; LPBYTE addr = module->baseAddr + pe_seg->VirtualAddress; TRACE("MapModule: " "Section %d at %08lx from %08lx len %08lx\n", i, (DWORD)addr, off, len); if ( _llseek(image, off, SEEK_SET) != off || _lread(image, addr, len) != len) error = TRUE; } _lclose(image); if (error) ERR("MapModule: Unable to load %s\n", module->pathName); else if (module->relocDelta != 0) { IMAGE_DATA_DIRECTORY *dir = nt_header->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_BASERELOC; IMAGE_BASE_RELOCATION *r = (IMAGE_BASE_RELOCATION *) (dir->Size? module->baseAddr + dir->VirtualAddress : 0); TRACE("MapModule: Reloc delta %08lx\n", module->relocDelta); while (r && r->VirtualAddress) { LPBYTE page = module->baseAddr + r->VirtualAddress; WORD *TypeOffset = (WORD *)(r + 1); int count = (r->SizeOfBlock - sizeof(*r)) / sizeof(*TypeOffset); TRACE("MapModule: %d relocations for page %08lx\n", count, (DWORD)page); for(i = 0; i < count; i++) { int offset = TypeOffset[i] & 0xFFF; int type = TypeOffset[i] >> 12; switch(type) { case IMAGE_REL_BASED_ABSOLUTE: break; case IMAGE_REL_BASED_HIGH: *(WORD *)(page+offset) += HIWORD(module->relocDelta); break; case IMAGE_REL_BASED_LOW: *(WORD *)(page+offset) += LOWORD(module->relocDelta); break; case IMAGE_REL_BASED_HIGHLOW: *(DWORD*)(page+offset) += module->relocDelta; break; default: WARN("MapModule: Unsupported fixup type\n"); break; } } r = (IMAGE_BASE_RELOCATION *)((LPBYTE)r + r->SizeOfBlock); } } context->Eax = 0; RESET_CFLAG(context); } break; case 0x0005: /* UnMap Module */ /* * Input: EDX: Flat address of module image * * Output: EAX: 1 if OK */ TRACE("UnMapModule: %lx\n", (DWORD)W32S_APP2WINE(context->Edx)); /* As we didn't map anything, there's nothing to unmap ... */ context->Eax = 1; break; case 0x0006: /* VirtualAlloc */ /* * Input: ECX: Current Process * * EDX: Flat address of arguments on stack * * DWORD *retv [out] Flat base address of allocated region * LPVOID base [in] Flat address of region to reserve/commit * DWORD size [in] Size of region * DWORD type [in] Type of allocation * DWORD prot [in] Type of access protection * * Output: EAX: NtStatus */ { DWORD *stack = (DWORD *)W32S_APP2WINE(context->Edx); DWORD *retv = (DWORD *)W32S_APP2WINE(stack[0]); LPVOID base = (LPVOID) W32S_APP2WINE(stack[1]); DWORD size = stack[2]; DWORD type = stack[3]; DWORD prot = stack[4]; DWORD result; TRACE("VirtualAlloc(%lx, %lx, %lx, %lx, %lx)\n", (DWORD)retv, (DWORD)base, size, type, prot); if (type & 0x80000000) { WARN("VirtualAlloc: strange type %lx\n", type); type &= 0x7fffffff; } if (!base && (type & MEM_COMMIT) && prot == PAGE_READONLY) { WARN("VirtualAlloc: NLS hack, allowing write access!\n"); prot = PAGE_READWRITE; } result = (DWORD)VirtualAlloc(base, size, type, prot); if (W32S_WINE2APP(result)) *retv = W32S_WINE2APP(result), context->Eax = STATUS_SUCCESS; else *retv = 0, context->Eax = STATUS_NO_MEMORY; /* FIXME */ } break; case 0x0007: /* VirtualFree */ /* * Input: ECX: Current Process * * EDX: Flat address of arguments on stack * * DWORD *retv [out] TRUE if success, FALSE if failure * LPVOID base [in] Flat address of region * DWORD size [in] Size of region * DWORD type [in] Type of operation * * Output: EAX: NtStatus */ { DWORD *stack = (DWORD *)W32S_APP2WINE(context->Edx); DWORD *retv = (DWORD *)W32S_APP2WINE(stack[0]); LPVOID base = (LPVOID) W32S_APP2WINE(stack[1]); DWORD size = stack[2]; DWORD type = stack[3]; DWORD result; TRACE("VirtualFree(%lx, %lx, %lx, %lx)\n", (DWORD)retv, (DWORD)base, size, type); result = VirtualFree(base, size, type); if (result) *retv = TRUE, context->Eax = STATUS_SUCCESS; else *retv = FALSE, context->Eax = STATUS_NO_MEMORY; /* FIXME */ } break; case 0x0008: /* VirtualProtect */ /* * Input: ECX: Current Process * * EDX: Flat address of arguments on stack * * DWORD *retv [out] TRUE if success, FALSE if failure * LPVOID base [in] Flat address of region * DWORD size [in] Size of region * DWORD new_prot [in] Desired access protection * DWORD *old_prot [out] Previous access protection * * Output: EAX: NtStatus */ { DWORD *stack = (DWORD *)W32S_APP2WINE(context->Edx); DWORD *retv = (DWORD *)W32S_APP2WINE(stack[0]); LPVOID base = (LPVOID) W32S_APP2WINE(stack[1]); DWORD size = stack[2]; DWORD new_prot = stack[3]; DWORD *old_prot = (DWORD *)W32S_APP2WINE(stack[4]); DWORD result; TRACE("VirtualProtect(%lx, %lx, %lx, %lx, %lx)\n", (DWORD)retv, (DWORD)base, size, new_prot, (DWORD)old_prot); result = VirtualProtect(base, size, new_prot, old_prot); if (result) *retv = TRUE, context->Eax = STATUS_SUCCESS; else *retv = FALSE, context->Eax = STATUS_NO_MEMORY; /* FIXME */ } break; case 0x0009: /* VirtualQuery */ /* * Input: ECX: Current Process * * EDX: Flat address of arguments on stack * * DWORD *retv [out] Nr. bytes returned * LPVOID base [in] Flat address of region * LPMEMORY_BASIC_INFORMATION info [out] Info buffer * DWORD len [in] Size of buffer * * Output: EAX: NtStatus */ { DWORD *stack = (DWORD *)W32S_APP2WINE(context->Edx); DWORD *retv = (DWORD *)W32S_APP2WINE(stack[0]); LPVOID base = (LPVOID) W32S_APP2WINE(stack[1]); LPMEMORY_BASIC_INFORMATION info = (LPMEMORY_BASIC_INFORMATION)W32S_APP2WINE(stack[2]); DWORD len = stack[3]; DWORD result; TRACE("VirtualQuery(%lx, %lx, %lx, %lx)\n", (DWORD)retv, (DWORD)base, (DWORD)info, len); result = VirtualQuery(base, info, len); *retv = result; context->Eax = STATUS_SUCCESS; } break; case 0x000A: /* SetVirtMemProcess */ /* * Input: ECX: Process Handle * * EDX: Flat address of region * * Output: EAX: NtStatus */ TRACE("[000a] ECX=%lx EDX=%lx\n", context->Ecx, context->Edx); /* FIXME */ context->Eax = STATUS_SUCCESS; break; case 0x000B: /* ??? some kind of cleanup */ /* * Input: ECX: Process Handle * * Output: EAX: NtStatus */ TRACE("[000b] ECX=%lx\n", context->Ecx); /* FIXME */ context->Eax = STATUS_SUCCESS; break; case 0x000C: /* Set Debug Flags */ /* * Input: EDX: Debug Flags * * Output: EDX: Previous Debug Flags */ FIXME("[000c] EDX=%lx\n", context->Edx); /* FIXME */ context->Edx = 0; break; case 0x000D: /* NtCreateSection */ /* * Input: EDX: Flat address of arguments on stack * * HANDLE32 *retv [out] Handle of Section created * DWORD flags1 [in] (?? unknown ??) * DWORD atom [in] Name of Section to create * LARGE_INTEGER *size [in] Size of Section * DWORD protect [in] Access protection * DWORD flags2 [in] (?? unknown ??) * HFILE32 hFile [in] Handle of file to map * DWORD psp [in] (Win32s: PSP that hFile belongs to) * * Output: EAX: NtStatus */ { DWORD *stack = (DWORD *) W32S_APP2WINE(context->Edx); HANDLE *retv = (HANDLE *)W32S_APP2WINE(stack[0]); DWORD flags1 = stack[1]; DWORD atom = stack[2]; LARGE_INTEGER *size = (LARGE_INTEGER *)W32S_APP2WINE(stack[3]); DWORD protect = stack[4]; DWORD flags2 = stack[5]; HANDLE hFile = DosFileHandleToWin32Handle(stack[6]); DWORD psp = stack[7]; HANDLE result = INVALID_HANDLE_VALUE; char name[128]; TRACE("NtCreateSection(%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx)\n", (DWORD)retv, flags1, atom, (DWORD)size, protect, flags2, (DWORD)hFile, psp); if (!atom || GlobalGetAtomNameA(atom, name, sizeof(name))) { TRACE("NtCreateSection: name=%s\n", atom? name : NULL); result = CreateFileMappingA(hFile, NULL, protect, size? size->s.HighPart : 0, size? size->s.LowPart : 0, atom? name : NULL); } if (result == INVALID_HANDLE_VALUE) WARN("NtCreateSection: failed!\n"); else TRACE("NtCreateSection: returned %lx\n", (DWORD)result); if (result != INVALID_HANDLE_VALUE) *retv = result, context->Eax = STATUS_SUCCESS; else *retv = result, context->Eax = STATUS_NO_MEMORY; /* FIXME */ } break; case 0x000E: /* NtOpenSection */ /* * Input: EDX: Flat address of arguments on stack * * HANDLE32 *retv [out] Handle of Section opened * DWORD protect [in] Access protection * DWORD atom [in] Name of Section to create * * Output: EAX: NtStatus */ { DWORD *stack = (DWORD *)W32S_APP2WINE(context->Edx); HANDLE *retv = (HANDLE *)W32S_APP2WINE(stack[0]); DWORD protect = stack[1]; DWORD atom = stack[2]; HANDLE result = INVALID_HANDLE_VALUE; char name[128]; TRACE("NtOpenSection(%lx, %lx, %lx)\n", (DWORD)retv, protect, atom); if (atom && GlobalGetAtomNameA(atom, name, sizeof(name))) { TRACE("NtOpenSection: name=%s\n", name); result = OpenFileMappingA(protect, FALSE, name); } if (result == INVALID_HANDLE_VALUE) WARN("NtOpenSection: failed!\n"); else TRACE("NtOpenSection: returned %lx\n", (DWORD)result); if (result != INVALID_HANDLE_VALUE) *retv = result, context->Eax = STATUS_SUCCESS; else *retv = result, context->Eax = STATUS_NO_MEMORY; /* FIXME */ } break; case 0x000F: /* NtCloseSection */ /* * Input: EDX: Flat address of arguments on stack * * HANDLE32 handle [in] Handle of Section to close * DWORD *id [out] Unique ID (?? unclear ??) * * Output: EAX: NtStatus */ { DWORD *stack = (DWORD *)W32S_APP2WINE(context->Edx); HANDLE handle = stack[0]; DWORD *id = (DWORD *)W32S_APP2WINE(stack[1]); TRACE("NtCloseSection(%lx, %lx)\n", (DWORD)handle, (DWORD)id); CloseHandle(handle); if (id) *id = 0; /* FIXME */ context->Eax = STATUS_SUCCESS; } break; case 0x0010: /* NtDupSection */ /* * Input: EDX: Flat address of arguments on stack * * HANDLE32 handle [in] Handle of Section to duplicate * * Output: EAX: NtStatus */ { DWORD *stack = (DWORD *)W32S_APP2WINE(context->Edx); HANDLE handle = stack[0]; HANDLE new_handle; TRACE("NtDupSection(%lx)\n", (DWORD)handle); DuplicateHandle( GetCurrentProcess(), handle, GetCurrentProcess(), &new_handle, 0, FALSE, DUPLICATE_SAME_ACCESS ); context->Eax = STATUS_SUCCESS; } break; case 0x0011: /* NtMapViewOfSection */ /* * Input: EDX: Flat address of arguments on stack * * HANDLE32 SectionHandle [in] Section to be mapped * DWORD ProcessHandle [in] Process to be mapped into * DWORD * BaseAddress [in/out] Address to be mapped at * DWORD ZeroBits [in] (?? unclear ??) * DWORD CommitSize [in] (?? unclear ??) * LARGE_INTEGER *SectionOffset [in] Offset within section * DWORD * ViewSize [in] Size of view * DWORD InheritDisposition [in] (?? unclear ??) * DWORD AllocationType [in] (?? unclear ??) * DWORD Protect [in] Access protection * * Output: EAX: NtStatus */ { DWORD * stack = (DWORD *)W32S_APP2WINE(context->Edx); HANDLE SectionHandle = stack[0]; DWORD ProcessHandle = stack[1]; /* ignored */ DWORD * BaseAddress = (DWORD *)W32S_APP2WINE(stack[2]); DWORD ZeroBits = stack[3]; DWORD CommitSize = stack[4]; LARGE_INTEGER *SectionOffset = (LARGE_INTEGER *)W32S_APP2WINE(stack[5]); DWORD * ViewSize = (DWORD *)W32S_APP2WINE(stack[6]); DWORD InheritDisposition = stack[7]; DWORD AllocationType = stack[8]; DWORD Protect = stack[9]; LPBYTE address = (LPBYTE)(BaseAddress? W32S_APP2WINE(*BaseAddress) : 0); DWORD access = 0, result; switch (Protect & ~(PAGE_GUARD|PAGE_NOCACHE)) { case PAGE_READONLY: access = FILE_MAP_READ; break; case PAGE_READWRITE: access = FILE_MAP_WRITE; break; case PAGE_WRITECOPY: access = FILE_MAP_COPY; break; case PAGE_EXECUTE_READ: access = FILE_MAP_READ; break; case PAGE_EXECUTE_READWRITE: access = FILE_MAP_WRITE; break; case PAGE_EXECUTE_WRITECOPY: access = FILE_MAP_COPY; break; } TRACE("NtMapViewOfSection" "(%lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx, %lx)\n", (DWORD)SectionHandle, ProcessHandle, (DWORD)BaseAddress, ZeroBits, CommitSize, (DWORD)SectionOffset, (DWORD)ViewSize, InheritDisposition, AllocationType, Protect); TRACE("NtMapViewOfSection: " "base=%lx, offset=%lx, size=%lx, access=%lx\n", (DWORD)address, SectionOffset? SectionOffset->s.LowPart : 0, ViewSize? *ViewSize : 0, access); result = (DWORD)MapViewOfFileEx(SectionHandle, access, SectionOffset? SectionOffset->s.HighPart : 0, SectionOffset? SectionOffset->s.LowPart : 0, ViewSize? *ViewSize : 0, address); TRACE("NtMapViewOfSection: result=%lx\n", result); if (W32S_WINE2APP(result)) { if (BaseAddress) *BaseAddress = W32S_WINE2APP(result); context->Eax = STATUS_SUCCESS; } else context->Eax = STATUS_NO_MEMORY; /* FIXME */ } break; case 0x0012: /* NtUnmapViewOfSection */ /* * Input: EDX: Flat address of arguments on stack * * DWORD ProcessHandle [in] Process (defining address space) * LPBYTE BaseAddress [in] Base address of view to be unmapped * * Output: EAX: NtStatus */ { DWORD *stack = (DWORD *)W32S_APP2WINE(context->Edx); DWORD ProcessHandle = stack[0]; /* ignored */ LPBYTE BaseAddress = (LPBYTE)W32S_APP2WINE(stack[1]); TRACE("NtUnmapViewOfSection(%lx, %lx)\n", ProcessHandle, (DWORD)BaseAddress); UnmapViewOfFile(BaseAddress); context->Eax = STATUS_SUCCESS; } break; case 0x0013: /* NtFlushVirtualMemory */ /* * Input: EDX: Flat address of arguments on stack * * DWORD ProcessHandle [in] Process (defining address space) * LPBYTE *BaseAddress [in?] Base address of range to be flushed * DWORD *ViewSize [in?] Number of bytes to be flushed * DWORD *unknown [???] (?? unknown ??) * * Output: EAX: NtStatus */ { DWORD *stack = (DWORD *)W32S_APP2WINE(context->Edx); DWORD ProcessHandle = stack[0]; /* ignored */ DWORD *BaseAddress = (DWORD *)W32S_APP2WINE(stack[1]); DWORD *ViewSize = (DWORD *)W32S_APP2WINE(stack[2]); DWORD *unknown = (DWORD *)W32S_APP2WINE(stack[3]); LPBYTE address = (LPBYTE)(BaseAddress? W32S_APP2WINE(*BaseAddress) : 0); DWORD size = ViewSize? *ViewSize : 0; TRACE("NtFlushVirtualMemory(%lx, %lx, %lx, %lx)\n", ProcessHandle, (DWORD)BaseAddress, (DWORD)ViewSize, (DWORD)unknown); TRACE("NtFlushVirtualMemory: base=%lx, size=%lx\n", (DWORD)address, size); FlushViewOfFile(address, size); context->Eax = STATUS_SUCCESS; } break; case 0x0014: /* Get/Set Debug Registers */ /* * Input: ECX: 0 if Get, 1 if Set * * EDX: Get: Flat address of buffer to receive values of * debug registers DR0 .. DR7 * Set: Flat address of buffer containing values of * debug registers DR0 .. DR7 to be set * Output: None */ FIXME("[0014] ECX=%lx EDX=%lx\n", context->Ecx, context->Edx); /* FIXME */ break; case 0x0015: /* Set Coprocessor Emulation Flag */ /* * Input: EDX: 0 to deactivate, 1 to activate coprocessor emulation * * Output: None */ TRACE("[0015] EDX=%lx\n", context->Edx); /* We don't care, as we always have a coprocessor anyway */ break; case 0x0016: /* Init Win32S VxD PSP */ /* * If called to query required PSP size: * * Input: EBX: 0 * Output: EDX: Required size of Win32s VxD PSP * * If called to initialize allocated PSP: * * Input: EBX: LoWord: Selector of Win32s VxD PSP * HiWord: Paragraph of Win32s VxD PSP (DOSMEM) * Output: None */ if (context->Ebx == 0) context->Edx = 0x80; else { PDB16 *psp = MapSL( MAKESEGPTR( BX_reg(context), 0 )); psp->nbFiles = 32; psp->fileHandlesPtr = MAKELONG(HIWORD(context->Ebx), 0x5c); memset((LPBYTE)psp + 0x5c, '\xFF', 32); } break; case 0x0017: /* Set Break Point */ /* * Input: EBX: Offset of Break Point * CX: Selector of Break Point * * Output: None */ FIXME("[0017] EBX=%lx CX=%x\n", context->Ebx, CX_reg(context)); /* FIXME */ break; case 0x0018: /* VirtualLock */ /* * Input: ECX: Current Process * * EDX: Flat address of arguments on stack * * DWORD *retv [out] TRUE if success, FALSE if failure * LPVOID base [in] Flat address of range to lock * DWORD size [in] Size of range * * Output: EAX: NtStatus */ { DWORD *stack = (DWORD *)W32S_APP2WINE(context->Edx); DWORD *retv = (DWORD *)W32S_APP2WINE(stack[0]); LPVOID base = (LPVOID) W32S_APP2WINE(stack[1]); DWORD size = stack[2]; DWORD result; TRACE("VirtualLock(%lx, %lx, %lx)\n", (DWORD)retv, (DWORD)base, size); result = VirtualLock(base, size); if (result) *retv = TRUE, context->Eax = STATUS_SUCCESS; else *retv = FALSE, context->Eax = STATUS_NO_MEMORY; /* FIXME */ } break; case 0x0019: /* VirtualUnlock */ /* * Input: ECX: Current Process * * EDX: Flat address of arguments on stack * * DWORD *retv [out] TRUE if success, FALSE if failure * LPVOID base [in] Flat address of range to unlock * DWORD size [in] Size of range * * Output: EAX: NtStatus */ { DWORD *stack = (DWORD *)W32S_APP2WINE(context->Edx); DWORD *retv = (DWORD *)W32S_APP2WINE(stack[0]); LPVOID base = (LPVOID) W32S_APP2WINE(stack[1]); DWORD size = stack[2]; DWORD result; TRACE("VirtualUnlock(%lx, %lx, %lx)\n", (DWORD)retv, (DWORD)base, size); result = VirtualUnlock(base, size); if (result) *retv = TRUE, context->Eax = STATUS_SUCCESS; else *retv = FALSE, context->Eax = STATUS_NO_MEMORY; /* FIXME */ } break; case 0x001A: /* KGetSystemInfo */ /* * Input: None * * Output: ECX: Start of sparse memory arena * EDX: End of sparse memory arena */ TRACE("KGetSystemInfo()\n"); /* * Note: Win32s reserves 0GB - 2GB for Win 3.1 and uses 2GB - 4GB as * sparse memory arena. We do it the other way around, since * we have to reserve 3GB - 4GB for Linux, and thus use * 0GB - 3GB as sparse memory arena. * * FIXME: What about other OSes ? */ context->Ecx = W32S_WINE2APP(0x00000000); context->Edx = W32S_WINE2APP(0xbfffffff); break; case 0x001B: /* KGlobalMemStat */ /* * Input: ESI: Flat address of buffer to receive memory info * * Output: None */ { struct Win32sMemoryInfo { DWORD DIPhys_Count; /* Total physical pages */ DWORD DIFree_Count; /* Free physical pages */ DWORD DILin_Total_Count; /* Total virtual pages (private arena) */ DWORD DILin_Total_Free; /* Free virtual pages (private arena) */ DWORD SparseTotal; /* Total size of sparse arena (bytes ?) */ DWORD SparseFree; /* Free size of sparse arena (bytes ?) */ }; struct Win32sMemoryInfo *info = (struct Win32sMemoryInfo *)W32S_APP2WINE(context->Esi); FIXME("KGlobalMemStat(%lx)\n", (DWORD)info); /* FIXME */ } break; case 0x001C: /* Enable/Disable Exceptions */ /* * Input: ECX: 0 to disable, 1 to enable exception handling * * Output: None */ TRACE("[001c] ECX=%lx\n", context->Ecx); /* FIXME */ break; case 0x001D: /* VirtualAlloc called from 16-bit code */ /* * Input: EDX: Segmented address of arguments on stack * * LPVOID base [in] Flat address of region to reserve/commit * DWORD size [in] Size of region * DWORD type [in] Type of allocation * DWORD prot [in] Type of access protection * * Output: EAX: NtStatus * EDX: Flat base address of allocated region */ { DWORD *stack = MapSL( MAKESEGPTR( LOWORD(context->Edx), HIWORD(context->Edx) )); LPVOID base = (LPVOID)W32S_APP2WINE(stack[0]); DWORD size = stack[1]; DWORD type = stack[2]; DWORD prot = stack[3]; DWORD result; TRACE("VirtualAlloc16(%lx, %lx, %lx, %lx)\n", (DWORD)base, size, type, prot); if (type & 0x80000000) { WARN("VirtualAlloc16: strange type %lx\n", type); type &= 0x7fffffff; } result = (DWORD)VirtualAlloc(base, size, type, prot); if (W32S_WINE2APP(result)) context->Edx = W32S_WINE2APP(result), context->Eax = STATUS_SUCCESS; else context->Edx = 0, context->Eax = STATUS_NO_MEMORY; /* FIXME */ TRACE("VirtualAlloc16: returning base %lx\n", context->Edx); } break; case 0x001E: /* VirtualFree called from 16-bit code */ /* * Input: EDX: Segmented address of arguments on stack * * LPVOID base [in] Flat address of region * DWORD size [in] Size of region * DWORD type [in] Type of operation * * Output: EAX: NtStatus * EDX: TRUE if success, FALSE if failure */ { DWORD *stack = MapSL( MAKESEGPTR( LOWORD(context->Edx), HIWORD(context->Edx) )); LPVOID base = (LPVOID)W32S_APP2WINE(stack[0]); DWORD size = stack[1]; DWORD type = stack[2]; DWORD result; TRACE("VirtualFree16(%lx, %lx, %lx)\n", (DWORD)base, size, type); result = VirtualFree(base, size, type); if (result) context->Edx = TRUE, context->Eax = STATUS_SUCCESS; else context->Edx = FALSE, context->Eax = STATUS_NO_MEMORY; /* FIXME */ } break; case 0x001F: /* FWorkingSetSize */ /* * Input: EDX: 0 if Get, 1 if Set * * ECX: Get: Buffer to receive Working Set Size * Set: Buffer containing Working Set Size * * Output: NtStatus */ { DWORD *ptr = (DWORD *)W32S_APP2WINE(context->Ecx); BOOL set = context->Edx; TRACE("FWorkingSetSize(%lx, %lx)\n", (DWORD)ptr, (DWORD)set); if (set) /* We do it differently ... */; else *ptr = 0x100; context->Eax = STATUS_SUCCESS; } break; default: VXD_BARF( context, "W32S" ); }
static void test_RegisterClipboardFormatA(void) { ATOM atom_id; UINT format_id, format_id2; char buf[256]; int len; BOOL ret; HANDLE handle; format_id = RegisterClipboardFormatA("my_cool_clipboard_format"); ok(format_id > 0xc000 && format_id < 0xffff, "invalid clipboard format id %04x\n", format_id); format_id2 = RegisterClipboardFormatA("MY_COOL_CLIPBOARD_FORMAT"); ok(format_id2 == format_id, "invalid clipboard format id %04x\n", format_id2); len = GetClipboardFormatNameA(format_id, buf, 256); ok(len == lstrlenA("my_cool_clipboard_format"), "wrong format name length %d\n", len); ok(!lstrcmpA(buf, "my_cool_clipboard_format"), "wrong format name \"%s\"\n", buf); lstrcpyA(buf, "foo"); SetLastError(0xdeadbeef); len = GetAtomNameA((ATOM)format_id, buf, 256); ok(len == 0, "GetAtomNameA should fail\n"); ok(GetLastError() == ERROR_INVALID_HANDLE, "err %d\n", GetLastError()); todo_wine { lstrcpyA(buf, "foo"); SetLastError(0xdeadbeef); len = GlobalGetAtomNameA((ATOM)format_id, buf, 256); ok(len == 0, "GlobalGetAtomNameA should fail\n"); ok(GetLastError() == ERROR_INVALID_HANDLE, "err %d\n", GetLastError()); } SetLastError(0xdeadbeef); atom_id = FindAtomA("my_cool_clipboard_format"); ok(atom_id == 0, "FindAtomA should fail\n"); ok(GetLastError() == ERROR_FILE_NOT_FOUND, "err %d\n", GetLastError()); if (0) { /* this relies on the clipboard and global atom table being different */ SetLastError(0xdeadbeef); atom_id = GlobalFindAtomA("my_cool_clipboard_format"); ok(atom_id == 0, "GlobalFindAtomA should fail\n"); ok(GetLastError() == ERROR_FILE_NOT_FOUND, "err %d\n", GetLastError()); } for (format_id = 0; format_id < 0xffff; format_id++) { SetLastError(0xdeadbeef); len = GetClipboardFormatNameA(format_id, buf, 256); if (format_id < 0xc000) ok(!len, "GetClipboardFormatNameA should fail, but it returned %d (%s)\n", len, buf); else if (len && winetest_debug > 1) trace("%04x: %s\n", format_id, len ? buf : ""); } ret = OpenClipboard(0); ok( ret, "OpenClipboard error %d\n", GetLastError()); /* try some invalid/unregistered formats */ SetLastError( 0xdeadbeef ); handle = SetClipboardData( 0, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 )); ok( !handle, "SetClipboardData succeeded\n" ); ok( GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "wrong error %u\n", GetLastError()); handle = SetClipboardData( 0x1234, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 )); ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError()); handle = SetClipboardData( 0x123456, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 )); ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError()); handle = SetClipboardData( 0xffff8765, GlobalAlloc( GMEM_DDESHARE | GMEM_MOVEABLE, 1 )); ok( handle != 0, "SetClipboardData failed err %d\n", GetLastError()); ok( IsClipboardFormatAvailable( 0x1234 ), "format missing\n" ); ok( IsClipboardFormatAvailable( 0x123456 ), "format missing\n" ); ok( IsClipboardFormatAvailable( 0xffff8765 ), "format missing\n" ); ok( !IsClipboardFormatAvailable( 0 ), "format available\n" ); ok( !IsClipboardFormatAvailable( 0x3456 ), "format available\n" ); ok( !IsClipboardFormatAvailable( 0x8765 ), "format available\n" ); trace("# of formats available: %d\n", CountClipboardFormats()); format_id = 0; while ((format_id = EnumClipboardFormats(format_id))) { ok(IsClipboardFormatAvailable(format_id), "format %04x was listed as available\n", format_id); len = GetClipboardFormatNameA(format_id, buf, 256); trace("%04x: %s\n", format_id, len ? buf : ""); } ret = EmptyClipboard(); ok( ret, "EmptyClipboard error %d\n", GetLastError()); ret =CloseClipboard(); ok( ret, "CloseClipboard error %d\n", GetLastError()); if (CountClipboardFormats()) { SetLastError(0xdeadbeef); ok(!EnumClipboardFormats(0), "EnumClipboardFormats should fail if clipboard wasn't open\n"); ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "Last error should be set to ERROR_CLIPBOARD_NOT_OPEN, not %d\n", GetLastError()); } SetLastError(0xdeadbeef); ok(!EmptyClipboard(), "EmptyClipboard should fail if clipboard wasn't open\n"); ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN || broken(GetLastError() == 0xdeadbeef), /* wow64 */ "Wrong error %u\n", GetLastError()); format_id = RegisterClipboardFormatA("#1234"); ok(format_id == 1234, "invalid clipboard format id %04x\n", format_id); }
static void test_RegisterClipboardFormatA(void) { ATOM atom_id; UINT format_id, format_id2; char buf[256]; int len; BOOL ret; format_id = RegisterClipboardFormatA("my_cool_clipboard_format"); ok(format_id > 0xc000 && format_id < 0xffff, "invalid clipboard format id %04x\n", format_id); format_id2 = RegisterClipboardFormatA("MY_COOL_CLIPBOARD_FORMAT"); ok(format_id2 == format_id, "invalid clipboard format id %04x\n", format_id2); len = GetClipboardFormatNameA(format_id, buf, 256); ok(len == lstrlenA("my_cool_clipboard_format"), "wrong format name length %d\n", len); ok(!lstrcmpA(buf, "my_cool_clipboard_format"), "wrong format name \"%s\"\n", buf); lstrcpyA(buf, "foo"); SetLastError(0xdeadbeef); len = GetAtomNameA((ATOM)format_id, buf, 256); ok(len == 0, "GetAtomNameA should fail\n"); test_last_error(ERROR_INVALID_HANDLE); todo_wine { lstrcpyA(buf, "foo"); SetLastError(0xdeadbeef); len = GlobalGetAtomNameA((ATOM)format_id, buf, 256); ok(len == 0, "GlobalGetAtomNameA should fail\n"); test_last_error(ERROR_INVALID_HANDLE); } SetLastError(0xdeadbeef); atom_id = FindAtomA("my_cool_clipboard_format"); ok(atom_id == 0, "FindAtomA should fail\n"); test_last_error(ERROR_FILE_NOT_FOUND); if (0) { /* this relies on the clipboard and global atom table being different */ SetLastError(0xdeadbeef); atom_id = GlobalFindAtomA("my_cool_clipboard_format"); ok(atom_id == 0, "GlobalFindAtomA should fail\n"); test_last_error(ERROR_FILE_NOT_FOUND); for (format_id = 0; format_id < 0xffff; format_id++) { SetLastError(0xdeadbeef); len = GetClipboardFormatNameA(format_id, buf, 256); if (format_id < 0xc000) { ok(!len, "GetClipboardFormatNameA should fail, but it returned %d (%s)\n", len, buf); test_last_error(ERROR_INVALID_PARAMETER); } else { if (len) trace("%04x: %s\n", format_id, len ? buf : ""); else test_last_error(ERROR_INVALID_HANDLE); } } } ret = OpenClipboard(0); ok( ret, "OpenClipboard error %d\n", GetLastError()); trace("# of formats available: %d\n", CountClipboardFormats()); format_id = 0; while ((format_id = EnumClipboardFormats(format_id))) { ok(IsClipboardFormatAvailable(format_id), "format %04x was listed as available\n", format_id); len = GetClipboardFormatNameA(format_id, buf, 256); trace("%04x: %s\n", format_id, len ? buf : ""); } ret = EmptyClipboard(); ok( ret, "EmptyClipboard error %d\n", GetLastError()); ret =CloseClipboard(); ok( ret, "CloseClipboard error %d\n", GetLastError()); if (CountClipboardFormats()) { SetLastError(0xdeadbeef); ok(!EnumClipboardFormats(0), "EnumClipboardFormats should fail if clipboard wasn't open\n"); ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN, "Last error should be set to ERROR_CLIPBOARD_NOT_OPEN, not %d\n", GetLastError()); } SetLastError(0xdeadbeef); ok(!EmptyClipboard(), "EmptyClipboard should fail if clipboard wasn't open\n"); ok(GetLastError() == ERROR_CLIPBOARD_NOT_OPEN || broken(GetLastError() == 0xdeadbeef), /* wow64 */ "Wrong error %u\n", GetLastError()); }