diff --git a/Include/dxwnd.h b/Include/dxwnd.h index 964fb1c..79c34d6 100644 --- a/Include/dxwnd.h +++ b/Include/dxwnd.h @@ -219,6 +219,8 @@ void OutTrace(const char *, ...); void *HookAPI(HMODULE, char *, void *, const char *, void *); void AdjustWindowFrame(HWND, DWORD, DWORD); LRESULT CALLBACK extWindowProc(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK extChildWindowProc(HWND, UINT, WPARAM, LPARAM); +LRESULT CALLBACK extDialogWindowProc(HWND, UINT, WPARAM, LPARAM); // defines below to condition debug message handling diff --git a/build/dxwnd.dll b/build/dxwnd.dll index 24693b1..adccf07 100644 --- a/build/dxwnd.dll +++ b/build/dxwnd.dll @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:459b90a107f873f78fcc7c496ce3f123d26d81bb920d47861f61eef1ae212a2d -size 469504 +oid sha256:08566b33e7a85d73883a1dedcb52c0be7fdb04f0e8cb8d6a44acd5404c8b2721 +size 471040 diff --git a/build/dxwnd.exe b/build/dxwnd.exe index 41ba1ea..f1b4d84 100644 --- a/build/dxwnd.exe +++ b/build/dxwnd.exe @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:098ce50e059091915a8a4ba91e8bbf8d4f8beb450acf641d471c0202627e080e -size 535552 +oid sha256:bdc5c58a5fba8b5b8013c2a5fdecfe9ba5fd024b73be5855891c120573a35f5b +size 537600 diff --git a/build/exports/Chicago 1930.dxw b/build/exports/Chicago 1930.dxw new file mode 100644 index 0000000..629f5b5 --- /dev/null +++ b/build/exports/Chicago 1930.dxw @@ -0,0 +1,26 @@ +[target] +title0=Chicago 1930 +path0=D:\Games\Chicago 1930\Chicago 1930.exe +module0= +opengllib0= +ver0=0 +coord0=0 +flag0=134234660 +flagg0=134217728 +flagh0=20 +flagi0=4325380 +tflag0=64 +initx0=0 +inity0=0 +minx0=0 +miny0=0 +maxx0=0 +maxy0=0 +posx0=50 +posy0=50 +sizx0=800 +sizy0=600 +maxfps0=0 +initts0=0 +winver0=0 +maxres0=-1 diff --git a/build/exports/Imperialism.dxw b/build/exports/Imperialism.dxw new file mode 100644 index 0000000..1678029 --- /dev/null +++ b/build/exports/Imperialism.dxw @@ -0,0 +1,26 @@ +[target] +title0=Imperialism +path0=D:\Games\Imperialism\Imperialism.exe +module0= +opengllib0= +ver0=0 +coord0=0 +flag0=1744839201 +flagg0=134217728 +flagh0=32788 +flagi0=4194308 +tflag0=6466 +initx0=0 +inity0=0 +minx0=0 +miny0=0 +maxx0=0 +maxy0=0 +posx0=50 +posy0=50 +sizx0=800 +sizy0=600 +maxfps0=0 +initts0=0 +winver0=0 +maxres0=-1 diff --git a/build/exports/Microsotf Motocross Madness 2.dxw b/build/exports/Microsotf Motocross Madness 2.dxw new file mode 100644 index 0000000..30a99b7 --- /dev/null +++ b/build/exports/Microsotf Motocross Madness 2.dxw @@ -0,0 +1,26 @@ +[target] +title0=Microsotf Motocross Madness 2 +path0=D:\Games\motocross madness 2\mcm2.exe +module0= +opengllib0= +ver0=0 +coord0=0 +flag0=134217760 +flagg0=1207959552 +flagh0=20 +flagi0=4194308 +tflag0=64 +initx0=0 +inity0=0 +minx0=0 +miny0=0 +maxx0=0 +maxy0=0 +posx0=50 +posy0=50 +sizx0=800 +sizy0=600 +maxfps0=0 +initts0=0 +winver0=0 +maxres0=-1 diff --git a/build/exports/dxwnd.ini b/build/exports/dxwnd.ini new file mode 100644 index 0000000..0d20e4d --- /dev/null +++ b/build/exports/dxwnd.ini @@ -0,0 +1,5 @@ +[window] +posx=1386 +posy=352 +sizx=320 +sizy=200 diff --git a/build/readme-relnotes.txt b/build/readme-relnotes.txt index feeee6b..eb43cee 100644 --- a/build/readme-relnotes.txt +++ b/build/readme-relnotes.txt @@ -449,3 +449,14 @@ added screen resolution choice: either a set of SVGA resolutions (mostly for 3:4 v2.02.69 improved exception catching to intercept memory violation exceptions and to neutralize offending code. Thank again to olly didasm lib, now the assembly instruction length is automatically determined so that the opcode can be replaced by the correct number of NOP instructions. If this doesn't mean much for you, just consider that this makes playable the Win95 (patched) release of "Star Wars Tie Fighter". fixed FillRect user32 call - brings some improvements to Imperialism (still far from being acceptable). + +v2.02.70 +GUI: +fixed saving wrong coordinates when dxwnd is terminated while minimized +added check for adminstrative capabilities on startup +DLL: +fix: moved DrawText/Ex api hooks into right library +fix: corrected child window procedure handling - fixes "Imperialism" child window closing +fixed FillRect coordinate handling - fixes "Imperialism" menus +fixed SetWindowPlacement handling + diff --git a/debug/dxwnd.ini b/debug/dxwnd.ini deleted file mode 100644 index f0228e4..0000000 --- a/debug/dxwnd.ini +++ /dev/null @@ -1,706 +0,0 @@ -[target] -title0=Genocide -path0=D:\Games\genocide\genocide.exe -module0= -opengllib0= -ver0=0 -coord0=1 -flag0=268435490 -flagg0=1207959552 -flagh0=65556 -flagi0=2097157 -tflag0=6403 -initx0=0 -inity0=0 -minx0=0 -miny0=0 -maxx0=0 -maxy0=0 -posx0=50 -posy0=50 -sizx0=800 -sizy0=600 -maxfps0=0 -initts0=0 -winver0=0 -maxres0=-1 -title1=WarWind -path1=D:\Games\WarWind\WW.EXE -module1= -opengllib1= -ver1=0 -coord1=0 -flag1=134234656 -flagg1=1207959552 -flagh1=20 -flagi1=4 -tflag1=6403 -initx1=0 -inity1=0 -minx1=0 -miny1=0 -maxx1=0 -maxy1=0 -posx1=50 -posy1=50 -sizx1=800 -sizy1=600 -maxfps1=0 -initts1=0 -winver1=0 -maxres1=-1 -title2=Galapagos -path2=D:\Games\Galapagos\GALA.EXE -module2= -opengllib2= -ver2=0 -coord2=0 -flag2=671090720 -flagg2=1207959552 -flagh2=20 -flagi2=4 -tflag2=0 -initx2=0 -inity2=0 -minx2=0 -miny2=0 -maxx2=0 -maxy2=0 -posx2=50 -posy2=50 -sizx2=800 -sizy2=600 -maxfps2=0 -initts2=0 -winver2=0 -maxres2=-1 -title3=Vangers -path3=D:\Games\Vangers\road.exe -module3= -opengllib3= -ver3=1 -coord3=0 -flag3=136315424 -flagg3=1207959552 -flagh3=20 -flagi3=524288 -tflag3=0 -initx3=0 -inity3=0 -minx3=0 -miny3=0 -maxx3=0 -maxy3=0 -posx3=50 -posy3=50 -sizx3=800 -sizy3=600 -maxfps3=0 -initts3=0 -winver3=0 -maxres3=-1 -title4=House of the Dead 2 -path4=*Hod2.exe -module4= -opengllib4= -ver4=0 -coord4=0 -flag4=754974752 -flagg4=1207959552 -flagh4=20 -flagi4=4 -tflag4=0 -initx4=0 -inity4=0 -minx4=0 -miny4=0 -maxx4=0 -maxy4=0 -posx4=50 -posy4=50 -sizx4=800 -sizy4=600 -maxfps4=0 -initts4=0 -winver4=0 -maxres4=-1 -title5=House of the Dead -path5=D:\Games\house of the dead\thotd.exe -module5= -opengllib5= -ver5=0 -coord5=0 -flag5=671089184 -flagg5=1207959680 -flagh5=4 -flagi5=4 -tflag5=6147 -initx5=0 -inity5=0 -minx5=0 -miny5=0 -maxx5=0 -maxy5=0 -posx5=50 -posy5=50 -sizx5=800 -sizy5=600 -maxfps5=0 -initts5=0 -winver5=0 -maxres5=-1 -title6=5th Element -path6=D:\Games\5th Element\PC.EXE -module6= -opengllib6= -ver6=0 -coord6=0 -flag6=134217760 -flagg6=1207959552 -flagh6=4 -flagi6=4 -tflag6=6147 -initx6=0 -inity6=0 -minx6=0 -miny6=0 -maxx6=0 -maxy6=0 -posx6=50 -posy6=50 -sizx6=800 -sizy6=600 -maxfps6=0 -initts6=0 -winver6=0 -maxres6=-1 -title7=Hydro Thunder -path7=D:\Games\Hydro Thunder\hydro.exe -module7= -opengllib7= -ver7=0 -coord7=0 -flag7=671088672 -flagg7=1207959552 -flagh7=20 -flagi7=4 -tflag7=0 -initx7=0 -inity7=0 -minx7=0 -miny7=0 -maxx7=0 -maxy7=0 -posx7=50 -posy7=50 -sizx7=800 -sizy7=600 -maxfps7=0 -initts7=0 -winver7=0 -maxres7=-1 -title8=Warcraft II BNE -path8=*Warcraft II BNE.exe -module8= -opengllib8= -ver8=0 -coord8=0 -flag8=134218272 -flagg8=1207959552 -flagh8=20 -flagi8=4 -tflag8=0 -initx8=0 -inity8=0 -minx8=0 -miny8=0 -maxx8=0 -maxy8=0 -posx8=50 -posy8=50 -sizx8=800 -sizy8=600 -maxfps8=0 -initts8=0 -winver8=0 -maxres8=-1 -title9=Virtua Fighter PC -path9=D:\Games\Virtua Fighter\VFPC.EXE -module9= -opengllib9= -ver9=0 -coord9=0 -flag9=134218272 -flagg9=134217744 -flagh9=20 -flagi9=4 -tflag9=0 -initx9=0 -inity9=0 -minx9=0 -miny9=0 -maxx9=0 -maxy9=0 -posx9=50 -posy9=50 -sizx9=800 -sizy9=600 -maxfps9=0 -initts9=0 -winver9=0 -maxres9=-1 -title10=Total Soccer 2000 (DirectX) -path10=D:\Games\Total Soccer 2000\SOCCERDX.EXE -module10= -opengllib10= -ver10=1 -coord10=0 -flag10=134234784 -flagg10=1208025344 -flagh10=20 -flagi10=12 -tflag10=0 -initx10=0 -inity10=0 -minx10=0 -miny10=0 -maxx10=0 -maxy10=0 -posx10=50 -posy10=50 -sizx10=800 -sizy10=600 -maxfps10=0 -initts10=2 -winver10=0 -maxres10=-1 -title11=Genocide (ORIGINAL FIXED) -path11=D:\Games\genocide\original vanilla (1998)\Genocide\genocide.exe -module11= -opengllib11= -ver11=0 -coord11=0 -flag11=134218272 -flagg11=1207959552 -flagh11=20 -flagi11=4 -tflag11=6403 -initx11=0 -inity11=0 -minx11=0 -miny11=0 -maxx11=0 -maxy11=0 -posx11=50 -posy11=50 -sizx11=800 -sizy11=600 -maxfps11=0 -initts11=0 -winver11=0 -maxres11=-1 -title12=Genocide (ORIGINAL BUGGED) -path12=D:\Games\genocide\original vanilla (1998)\Genocide\genocide.orig.exe -module12= -opengllib12= -ver12=0 -coord12=0 -flag12=134218272 -flagg12=1207959552 -flagh12=20 -flagi12=4 -tflag12=0 -initx12=0 -inity12=0 -minx12=0 -miny12=0 -maxx12=0 -maxy12=0 -posx12=50 -posy12=50 -sizx12=800 -sizy12=600 -maxfps12=0 -initts12=0 -winver12=0 -maxres12=-1 -title13=Genocide (REMIXED VERSION) -path13=D:\Games\genocide\remixed version (1999)\genocide\genocide.exe -module13= -opengllib13= -ver13=0 -coord13=0 -flag13=134218272 -flagg13=1207959552 -flagh13=20 -flagi13=4194308 -tflag13=6403 -initx13=0 -inity13=0 -minx13=0 -miny13=0 -maxx13=0 -maxy13=0 -posx13=50 -posy13=50 -sizx13=800 -sizy13=600 -maxfps13=0 -initts13=0 -winver13=0 -maxres13=-1 -title14=Final Fantasy VII -path14=D:\Games\Final Fantasy 7\ff7.exe -module14= -opengllib14= -ver14=0 -coord14=0 -flag14=713032224 -flagg14=1208090880 -flagh14=65541 -flagi14=4194308 -tflag14=6147 -initx14=0 -inity14=0 -minx14=0 -miny14=0 -maxx14=0 -maxy14=0 -posx14=50 -posy14=50 -sizx14=800 -sizy14=600 -maxfps14=0 -initts14=0 -winver14=0 -maxres14=-1 -title15=Final Fighter -path15=D:\Games\FinalFighter\FinalFighter.exe -module15= -opengllib15= -ver15=1 -coord15=0 -flag15=-1476394464 -flagg15=1209008128 -flagh15=20 -flagi15=4 -tflag15=0 -initx15=0 -inity15=0 -minx15=0 -miny15=0 -maxx15=0 -maxy15=0 -posx15=50 -posy15=50 -sizx15=800 -sizy15=600 -maxfps15=0 -initts15=0 -winver15=0 -maxres15=-1 -title16=Flight Simulator 98 -path16=D:\Games\Flight Simulator 98\FLTSIM98.EXE -module16= -opengllib16= -ver16=0 -coord16=0 -flag16=679477282 -flagg16=1207959552 -flagh16=20 -flagi16=4 -tflag16=0 -initx16=0 -inity16=0 -minx16=0 -miny16=0 -maxx16=0 -maxy16=0 -posx16=50 -posy16=50 -sizx16=800 -sizy16=600 -maxfps16=0 -initts16=0 -winver16=0 -maxres16=-1 -title17=Flying Heroes -path17=D:\Games\Flying_Heroes\fh.exe -module17= -opengllib17= -ver17=0 -coord17=0 -flag17=419446820 -flagg17=1207959552 -flagh17=20 -flagi17=4 -tflag17=0 -initx17=0 -inity17=0 -minx17=0 -miny17=0 -maxx17=0 -maxy17=0 -posx17=50 -posy17=50 -sizx17=800 -sizy17=600 -maxfps17=0 -initts17=0 -winver17=0 -maxres17=-1 -title18=Final Fantasy VIII -path18=D:\Games\Final Fantasy VIII\FF8.exe -module18= -opengllib18= -ver18=0 -coord18=0 -flag18=134218272 -flagg18=1207959552 -flagh18=20 -flagi18=4 -tflag18=0 -initx18=0 -inity18=0 -minx18=0 -miny18=0 -maxx18=0 -maxy18=0 -posx18=50 -posy18=50 -sizx18=800 -sizy18=600 -maxfps18=0 -initts18=0 -winver18=0 -maxres18=-1 -title19=Jazz Jackrabbit 2 -path19=D:\Games\Jazz Jackrabbit 2\JAZZ2.EXE -module19= -opengllib19= -ver19=0 -coord19=0 -flag19=671097376 -flagg19=1207959552 -flagh19=20 -flagi19=4 -tflag19=0 -initx19=0 -inity19=0 -minx19=0 -miny19=0 -maxx19=0 -maxy19=0 -posx19=50 -posy19=50 -sizx19=800 -sizy19=600 -maxfps19=0 -initts19=0 -winver19=0 -maxres19=-1 -title20=Jazz Jackrabbit 3D -path20=D:\Games\Jazz Jackrabbit 3D\System\Jazz3d.exe -module20= -opengllib20= -ver20=9 -coord20=0 -flag20=134217728 -flagg20=134217728 -flagh20=20 -flagi20=4 -tflag20=0 -initx20=0 -inity20=0 -minx20=0 -miny20=0 -maxx20=0 -maxy20=0 -posx20=50 -posy20=50 -sizx20=800 -sizy20=600 -maxfps20=0 -initts20=0 -winver20=0 -maxres20=-1 -title21=Moon Child -path21=D:\Games\Moonchld\MC.EXE -module21= -opengllib21= -ver21=0 -coord21=0 -flag21=134218272 -flagg21=1207959552 -flagh21=20 -flagi21=4718592 -tflag21=6211 -initx21=0 -inity21=0 -minx21=0 -miny21=0 -maxx21=0 -maxy21=0 -posx21=50 -posy21=50 -sizx21=800 -sizy21=600 -maxfps21=0 -initts21=0 -winver21=0 -maxres21=-1 -title22=Motocross Madness -path22=D:\Games\Motocross Madness\GAME\MCM.EXE -module22= -opengllib22= -ver22=0 -coord22=0 -flag22=134218272 -flagg22=1207959552 -flagh22=20 -flagi22=4194308 -tflag22=64 -initx22=0 -inity22=0 -minx22=0 -miny22=0 -maxx22=0 -maxy22=0 -posx22=50 -posy22=50 -sizx22=800 -sizy22=600 -maxfps22=0 -initts22=0 -winver22=0 -maxres22=-1 -title23=Diablo -path23=D:\Games\Diablo\Diablo.exe -module23= -opengllib23= -ver23=1 -coord23=0 -flag23=138428450 -flagg23=1108344848 -flagh23=20 -flagi23=0 -tflag23=0 -initx23=0 -inity23=0 -minx23=0 -miny23=0 -maxx23=0 -maxy23=0 -posx23=50 -posy23=50 -sizx23=640 -sizy23=480 -maxfps23=0 -initts23=0 -winver23=0 -maxres23=0 -title24=Star Wars Tie Fighter -path24=D:\Games\TIE95\TIE95.EXE -module24= -opengllib24= -ver24=0 -coord24=0 -flag24=134217843 -flagg24=1207959568 -flagh24=20 -flagi24=4261892 -tflag24=6466 -initx24=0 -inity24=0 -minx24=0 -miny24=0 -maxx24=0 -maxy24=0 -posx24=50 -posy24=50 -sizx24=800 -sizy24=600 -maxfps24=0 -initts24=6 -winver24=0 -maxres24=-1 -title25=Imperialism -path25=D:\Games\Imperialism\Imperialism.exe -module25= -opengllib25= -ver25=0 -coord25=0 -flag25=1610744353 -flagg25=134217728 -flagh25=32788 -flagi25=4194308 -tflag25=6211 -initx25=0 -inity25=0 -minx25=0 -miny25=0 -maxx25=0 -maxy25=0 -posx25=50 -posy25=50 -sizx25=800 -sizy25=600 -maxfps25=0 -initts25=0 -winver25=0 -maxres25=-1 -title26=Imperialism II -path26=D:\Games\Imperialism 2\imperialism II.exe -module26= -opengllib26= -ver26=0 -coord26=0 -flag26=679485474 -flagg26=1207959552 -flagh26=32788 -flagi26=4 -tflag26=0 -initx26=0 -inity26=0 -minx26=0 -miny26=0 -maxx26=0 -maxy26=0 -posx26=50 -posy26=50 -sizx26=800 -sizy26=600 -maxfps26=0 -initts26=0 -winver26=0 -maxres26=0 -title27=Premier Manager 98 -path27=D:\Games\Premier Manager 98\MANAGER.EXE -module27= -opengllib27= -ver27=0 -coord27=0 -flag27=671088674 -flagg27=1207959552 -flagh27=32784 -flagi27=4194304 -tflag27=6403 -initx27=0 -inity27=0 -minx27=0 -miny27=0 -maxx27=0 -maxy27=0 -posx27=50 -posy27=50 -sizx27=800 -sizy27=600 -maxfps27=0 -initts27=0 -winver27=0 -maxres27=0 -[window] -posx=986 -posy=424 -sizx=320 -sizy=200 diff --git a/dll/ddraw.cpp b/dll/ddraw.cpp index 26f08b5..25afba5 100644 --- a/dll/ddraw.cpp +++ b/dll/ddraw.cpp @@ -3951,8 +3951,8 @@ static BOOL CheckResolutionLimit(LPDDSURFACEDESC lpDDSurfaceDesc) { #define HUGE 100000 DWORD maxw, maxh; + maxw=HUGE; maxh=HUGE; switch(dxw.MaxScreenRes){ - case DXW_NO_LIMIT: maxw=HUGE; maxh=HUGE; break; case DXW_LIMIT_320x200: maxw=320; maxh=200; break; case DXW_LIMIT_640x480: maxw=640; maxh=480; break; case DXW_LIMIT_800x600: maxw=800; maxh=600; break; @@ -4018,7 +4018,7 @@ HRESULT WINAPI myEnumModesFilterNative(LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID l if((dxw.dwFlags4 & LIMITSCREENRES) && CheckResolutionLimit(lpDDSurfaceDesc)) return DDENUMRET_OK; res=(*((NewContext_Type *)lpContext)->lpCallback)(lpDDSurfaceDesc, ((NewContext_Type *)lpContext)->lpContext); - OutTraceDW("EnumDisplayModes(D): proposed size=(%d,%d) res=%x\n", lpDDSurfaceDesc->dwWidth, lpDDSurfaceDesc->dwHeight, res); + OutTraceDW("EnumDisplayModes(D): native size=(%d,%d) res=%x\n", lpDDSurfaceDesc->dwWidth, lpDDSurfaceDesc->dwHeight, res); return res; } diff --git a/dll/dinput.cpp b/dll/dinput.cpp index c007538..4f0d3da 100644 --- a/dll/dinput.cpp +++ b/dll/dinput.cpp @@ -1,4 +1,5 @@ #define DIRECTINPUT_VERSION 0x800 +#define _CRT_SECURE_NO_WARNINGS #include #include @@ -226,7 +227,7 @@ HRESULT WINAPI extGetDeviceData(LPDIRECTINPUTDEVICE lpdid, DWORD cbdata, LPVOID if(!dxw.bActive) *pdwinout = 0; GetMousePosition((int *)&p.x, (int *)&p.y); - if(cbdata == 20 || cbdata == 24){ + if(cbdata == 20 || cbdata == 24 || cbdata == 16){ tmp = (BYTE *)rgdod; for(i = 0; i < *pdwinout; i ++){ if(((LPDIDEVICEOBJECTDATA)tmp)->dwOfs == DIMOFS_X){ @@ -259,7 +260,7 @@ HRESULT WINAPI extGetDeviceState(LPDIRECTINPUTDEVICE lpdid, DWORD cbdata, LPDIMO HRESULT res; POINT p = {0, 0}; - OutTraceDW("GetDeviceState(I): cbData=%i,%i\n", cbdata, dxw.bActive); + OutTraceDW("GetDeviceState(I): did=%x cbData=%i,%i\n", lpdid, cbdata, dxw.bActive); res = (*pGetDeviceState)(lpdid, cbdata, lpvdata); if(res) return res; @@ -290,7 +291,7 @@ HRESULT WINAPI extGetDeviceState(LPDIRECTINPUTDEVICE lpdid, DWORD cbdata, LPDIMO HRESULT WINAPI extSetDataFormat(LPDIRECTINPUTDEVICE lpdid, LPCDIDATAFORMAT lpdf) { - OutTraceDW("SetDataFormat(I): flags=0x%x\n", lpdf->dwFlags); + OutTraceDW("SetDataFormat(I): did=%x flags=0x%x\n", lpdid, lpdf->dwFlags); if(lpdf->dwFlags & DIDF_ABSAXIS) dxw.bDInputAbs = 1; if(lpdf->dwFlags & DIDF_RELAXIS) dxw.bDInputAbs = 0; @@ -299,8 +300,9 @@ HRESULT WINAPI extSetDataFormat(LPDIRECTINPUTDEVICE lpdid, LPCDIDATAFORMAT lpdf) HRESULT WINAPI extDISetCooperativeLevel(LPDIRECTINPUTDEVICE lpdid, HWND hwnd, DWORD dwflags) { - OutTraceDW("SetCooperativeLevel(I)\n"); + OutTraceDW("SetCooperativeLevel(I): did=%x hwnd=%x flags=%x\n", lpdid, hwnd, dwflags); + if(dxw.IsRealDesktop(hwnd)) hwnd=dxw.GethWnd(); dwflags = DISCL_NONEXCLUSIVE | DISCL_BACKGROUND; return (*pDISetCooperativeLevel)(lpdid, hwnd, dwflags); } diff --git a/dll/dxhook.cpp b/dll/dxhook.cpp index 7d28008..1f57186 100644 --- a/dll/dxhook.cpp +++ b/dll/dxhook.cpp @@ -563,7 +563,9 @@ void HookWindowProc(HWND hwnd) { WNDPROC pWindowProc; pWindowProc = (WNDPROC)(*pGetWindowLong)(hwnd, GWL_WNDPROC); - if (pWindowProc == extWindowProc){ + if ((pWindowProc == extWindowProc) || + (pWindowProc == extChildWindowProc) || + (pWindowProc == extDialogWindowProc)){ // hooked already !!! OutTraceDW("GetWindowLong: hwnd=%x WindowProc HOOK already in place\n", hwnd); } @@ -618,7 +620,7 @@ void AdjustWindowFrame(HWND hwnd, DWORD width, DWORD height) (*pInvalidateRect)(hwnd, NULL, TRUE); } -INT_PTR CALLBACK extDialogWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) +LRESULT CALLBACK extDialogWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { static int i=0; static WINDOWPOS *wp; @@ -693,7 +695,9 @@ LRESULT CALLBACK extChildWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPAR } pWindowProc=WhndGetWindowProc(hwnd); + if(pWindowProc) return(*pWindowProc)(hwnd, message, wparam, lparam); + return DefWindowProc(hwnd, message, wparam, lparam); } diff --git a/dll/dxwcore.cpp b/dll/dxwcore.cpp index c407801..7ef298b 100644 --- a/dll/dxwcore.cpp +++ b/dll/dxwcore.cpp @@ -116,6 +116,23 @@ void dxwCore::SetScreenSize(int x, int y) p->Width = (short)dwScreenWidth; p->Height = (short)dwScreenHeight; } + if(dwFlags4 & LIMITSCREENRES){ + #define HUGE 100000 + DWORD maxw, maxh; + maxw=HUGE; maxh=HUGE; + switch(dxw.MaxScreenRes){ + case DXW_LIMIT_320x200: maxw=320; maxh=200; break; + case DXW_LIMIT_640x480: maxw=640; maxh=480; break; + case DXW_LIMIT_800x600: maxw=800; maxh=600; break; + case DXW_LIMIT_1024x768: maxw=1024; maxh=768; break; + case DXW_LIMIT_1280x960: maxw=1280; maxh=960; break; + } + if(((DWORD)p->Width > maxw) || ((DWORD)p->Height > maxh)){ + OutTraceDW("DXWND: limit device size=(%d,%d)\n", maxw, maxh); + p->Width = (short)maxw; + p->Height = (short)maxh; + } + } } /* ------------------------------------------------------------------ */ @@ -1382,7 +1399,7 @@ HDC dxwCore::AcquireEmulatedDC(HWND hwnd) { HDC wdc; if(!(wdc=(*pGDIGetDC)(hwnd))) - OutTraceE("GetDC: ERROR err=%d at=%d\n", GetLastError(), __LINE__); + OutTraceE("GetDC: ERROR err=%d at=%d\n", GetLastError(), __LINE__); return AcquireEmulatedDC(wdc); } diff --git a/dll/dxwnd.cpp b/dll/dxwnd.cpp index cabc65e..ae87207 100644 --- a/dll/dxwnd.cpp +++ b/dll/dxwnd.cpp @@ -24,7 +24,7 @@ along with this program. If not, see . #include "dxwnd.h" #include "dxwcore.hpp" -#define VERSION "2.02.69" +#define VERSION "2.02.70" #define DDTHREADLOCK 1 diff --git a/dll/dxwnd.vs2008.suo b/dll/dxwnd.vs2008.suo index a53db6a..3f242f6 100644 Binary files a/dll/dxwnd.vs2008.suo and b/dll/dxwnd.vs2008.suo differ diff --git a/dll/gdi32.cpp b/dll/gdi32.cpp index fb17f83..e9509cc 100644 --- a/dll/gdi32.cpp +++ b/dll/gdi32.cpp @@ -28,7 +28,17 @@ static void Stopper(char *s, int line) if(t->flags & MAPGDITOPRIMARY) dlg->m_DCEmulationMode = 3; */ +typedef BOOL (WINAPI *ExtTextOutW_Type)(HDC, int, int, UINT, const RECT *, LPCWSTR, UINT, const INT *); +typedef BOOL (WINAPI *ExtTextOutA_Type)(HDC, int, int, UINT, const RECT *, LPCSTR, UINT, const INT *); +BOOL WINAPI extExtTextOutW(HDC, int, int, UINT, const RECT *, LPCWSTR, UINT, const INT *); +BOOL WINAPI extExtTextOutA(HDC, int, int, UINT, const RECT *, LPCSTR, UINT, const INT *); +ExtTextOutW_Type pExtTextOutW = NULL; +ExtTextOutA_Type pExtTextOutA = NULL; + static HookEntry_Type Hooks[]={ + {"ExtTextOutA", (FARPROC)ExtTextOutA, (FARPROC *)&pExtTextOutA, (FARPROC)extExtTextOutA}, + {"ExtTextOutW", (FARPROC)ExtTextOutW, (FARPROC *)&pExtTextOutW, (FARPROC)extExtTextOutW}, + {"GetDeviceCaps", (FARPROC)GetDeviceCaps, (FARPROC *)&pGDIGetDeviceCaps, (FARPROC)extGetDeviceCaps}, {"ScaleWindowExtEx", (FARPROC)ScaleWindowExtEx, (FARPROC *)&pGDIScaleWindowExtEx, (FARPROC)extScaleWindowExtEx}, {"SaveDC", (FARPROC)SaveDC, (FARPROC *)&pGDISaveDC, (FARPROC)extGDISaveDC}, @@ -84,9 +94,6 @@ static HookEntry_Type ScaledHooks[]={ //{"CreateRectRgn", (FARPROC)NULL, (FARPROC *)&pCreateRectRgn, (FARPROC)extCreateRectRgn}, //{"CreateRectRgnIndirect", (FARPROC)NULL, (FARPROC *)&pCreateRectRgnIndirect, (FARPROC)extCreateRectRgnIndirect}, //{"CreatePolygonRgn", (FARPROC)NULL, (FARPROC *)&pCreatePolygonRgn, (FARPROC)extCreatePolygonRgn}, - {"DrawTextA", (FARPROC)NULL, (FARPROC *)&pDrawText, (FARPROC)extDrawText}, - {"DrawTextExA", (FARPROC)NULL, (FARPROC *)&pDrawTextEx, (FARPROC)extDrawTextEx}, - // same as emulated GDI ... {"CreateCompatibleDC", (FARPROC)CreateCompatibleDC, (FARPROC *)&pGDICreateCompatibleDC, (FARPROC)extGDICreateCompatibleDC}, {"DeleteDC", (FARPROC)DeleteDC, (FARPROC *)&pGDIDeleteDC, (FARPROC)extGDIDeleteDC}, @@ -114,7 +121,6 @@ static HookEntry_Type EmulateHooks[]={ {"GetObjectType", (FARPROC)GetObjectType, (FARPROC *)&pGetObjectType, (FARPROC)extGetObjectType}, {"GetClipBox", (FARPROC)NULL, (FARPROC *)&pGDIGetClipBox, (FARPROC)extGetClipBox}, - {0, NULL, 0, 0} // terminator }; @@ -1533,38 +1539,6 @@ HRGN WINAPI extCreatePolygonRgn(const POINT *lpPoints, int cPoints, int fnPolyFi return ret; } -int WINAPI extDrawText(HDC hdc, LPCTSTR lpchText, int nCount, LPRECT lpRect, UINT uFormat) -{ - int ret; - OutTraceDW("DrawText: hdc=%x rect=(%d,%d)-(%d,%d) Format=%x Text=(%d)\"%s\"\n", - hdc, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, uFormat, nCount, lpchText); - - if (dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hdc))){ - dxw.MapClient((RECT *)lpRect); - OutTraceDW("DrawText: fixed rect=(%d,%d)-(%d,%d)\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); - } - - ret=(*pDrawText)(hdc, lpchText, nCount, lpRect, uFormat); - if(!ret) OutTraceE("DrawText: ERROR ret=%x err=%d\n", ret, GetLastError()); - return ret; -} - -int WINAPI extDrawTextEx(HDC hdc, LPTSTR lpchText, int nCount, LPRECT lpRect, UINT dwDTFormat, LPDRAWTEXTPARAMS lpDTParams) -{ - int ret; - OutTraceDW("DrawTextEx: hdc=%x rect=(%d,%d)-(%d,%d) DTFormat=%x Text=(%d)\"%s\"\n", - hdc, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, dwDTFormat, nCount, lpchText); - - if (dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hdc))){ - dxw.MapClient((RECT *)lpRect); - OutTraceDW("DrawTextEx: fixed rect=(%d,%d)-(%d,%d)\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); - } - - ret=(*pDrawTextEx)(hdc, lpchText, nCount, lpRect, dwDTFormat, lpDTParams); - if(!ret) OutTraceE("DrawTextEx: ERROR ret=%x err=%d\n", ret, GetLastError()); - return ret; -} - BOOL WINAPI extMaskBlt(HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HDC hdcSrc, int nXSrc, int nYSrc, HBITMAP hbmMask, int xMask, int yMask, DWORD dwRop) { @@ -1894,4 +1868,44 @@ BOOL SetTextJustification( _In_ int nBreakExtra, <---- _In_ int nBreakCount ); -#endif \ No newline at end of file +#endif + +BOOL WINAPI extExtTextOutA(HDC hdc, int X, int Y, UINT fuOptions, const RECT *lprc, LPCSTR lpString, UINT cbCount, const INT *lpDx) +{ + OutTrace("ExtTextOutA: pos=(%d,%d) String=\"%s\"\n", X, Y, lpString); + //if (dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hdc))){ + // dxw.MapClient(&X, &Y); + // if(lprc) dxw.MapClient((LPRECT)lprc); + // OutTraceDW("ExtTextOutA: fixed pos=(%d,%d)\n", X, Y); + //} + return (*pExtTextOutA)(hdc, X, Y, fuOptions, lprc, lpString, cbCount, lpDx); +} + +extern BOOL gFixed; + +BOOL WINAPI extExtTextOutW(HDC hdc, int X, int Y, UINT fuOptions, const RECT *lprc, LPCWSTR lpString, UINT cbCount, const INT *lpDx) +{ + RECT rc; + if(IsTraceDW){ + OutTrace("ExtTextOutW: hdc=%x pos=(%d,%d) String=\"%ls\" rect=", hdc, X, Y, lpString); + if(lprc) + OutTrace("(%d,%d)-(%d,%d)\n", lprc->left, lprc->top, lprc->right, lprc->bottom); + else + OutTrace("NULL\n"); + } + + //return (*pExtTextOutW)(hdc, X, Y, fuOptions, lprc, lpString, cbCount, lpDx); + + if (dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hdc)) && !gFixed){ + //dxw.UnmapClient(&X, &Y); + //if(lprc) dxw.UnmapClient(&rc); + dxw.MapClient(&X, &Y); + if(lprc) dxw.MapClient(&rc); + OutTraceDW("ExtTextOutW: fixed pos=(%d,%d)\n", X, Y); + } + if(lprc) + return (*pExtTextOutW)(hdc, X, Y, fuOptions, &rc, lpString, cbCount, lpDx); + else + return (*pExtTextOutW)(hdc, X, Y, fuOptions, NULL, lpString, cbCount, lpDx); + +} diff --git a/dll/syslibs.h b/dll/syslibs.h index ca6201c..3c169ce 100644 --- a/dll/syslibs.h +++ b/dll/syslibs.h @@ -80,8 +80,6 @@ typedef HRGN (WINAPI *CreateEllipticRgnIndirect_Type)(const RECT *); typedef HRGN (WINAPI *CreateRectRgn_Type)(int, int, int, int); typedef HRGN (WINAPI *CreateRectRgnIndirect_Type)(const RECT *); typedef HRGN (WINAPI *CreatePolygonRgn_Type)(const POINT *, int, int); -typedef int (WINAPI *DrawText_Type)(HDC, LPCTSTR, int, LPRECT, UINT); -typedef int (WINAPI *DrawTextEx_Type)(HDC, LPTSTR, int, LPRECT, UINT, LPDRAWTEXTPARAMS); typedef BOOL (WINAPI *MaskBlt_Type)(HDC, int, int, int, int, HDC, int, int, HBITMAP, int, int, DWORD); typedef BOOL (WINAPI *SetViewportOrgEx_Type)(HDC, int, int, LPPOINT); typedef BOOL (WINAPI *SetViewportExtEx_Type)(HDC, int, int, LPSIZE); @@ -149,6 +147,8 @@ typedef HWND (WINAPI *CreateDialogParam_Type)(HINSTANCE, LPCTSTR, HWND, DLGPROC, typedef HWND (WINAPI *CreateWindowExA_Type)(DWORD, LPCTSTR, LPCTSTR, DWORD, int, int, int, int, HWND, HMENU, HINSTANCE, LPVOID); typedef HWND (WINAPI *CreateWindowExW_Type)(DWORD, LPCWSTR, LPCWSTR, DWORD, int, int, int, int, HWND, HMENU, HINSTANCE, LPVOID); typedef LRESULT (WINAPI *DefWindowProc_Type)(HWND, UINT, WPARAM, LPARAM); +typedef int (WINAPI *DrawText_Type)(HDC, LPCTSTR, int, LPRECT, UINT); +typedef int (WINAPI *DrawTextEx_Type)(HDC, LPTSTR, int, LPRECT, UINT, LPDRAWTEXTPARAMS); typedef BOOL (WINAPI *EndPaint_Type)(HWND, const PAINTSTRUCT *); typedef LONG (WINAPI *EnumDisplaySettings_Type)(LPCTSTR, DWORD, LPDEVMODEA); typedef int (WINAPI *FillRect_Type)(HDC, const RECT *, HBRUSH); @@ -282,8 +282,6 @@ DXWEXTERN CreateEllipticRgnIndirect_Type pCreateEllipticRgnIndirect DXWINITIALIZ DXWEXTERN CreateRectRgn_Type pCreateRectRgn DXWINITIALIZED; DXWEXTERN CreateRectRgnIndirect_Type pCreateRectRgnIndirect DXWINITIALIZED; DXWEXTERN CreatePolygonRgn_Type pCreatePolygonRgn DXWINITIALIZED; -DXWEXTERN DrawText_Type pDrawText DXWINITIALIZED; -DXWEXTERN DrawTextEx_Type pDrawTextEx DXWINITIALIZED; DXWEXTERN MaskBlt_Type pMaskBlt DXWINITIALIZED; DXWEXTERN SetViewportOrgEx_Type pSetViewportOrgEx DXWINITIALIZED; DXWEXTERN SetViewportExtEx_Type pSetViewportExtEx DXWINITIALIZED; @@ -348,6 +346,8 @@ DXWEXTERN CreateDialogParam_Type pCreateDialogParam DXWINITIALIZED; DXWEXTERN CreateWindowExA_Type pCreateWindowExA DXWINITIALIZED; DXWEXTERN CreateWindowExW_Type pCreateWindowExW DXWINITIALIZED; DXWEXTERN DefWindowProc_Type pDefWindowProc DXWINITIALIZED; +DXWEXTERN DrawText_Type pDrawText DXWINITIALIZED; +DXWEXTERN DrawTextEx_Type pDrawTextEx DXWINITIALIZED; DXWEXTERN EndPaint_Type pEndPaint DXWINITIALIZED; DXWEXTERN EnumDisplaySettings_Type pEnumDisplaySettings DXWINITIALIZED; DXWEXTERN FillRect_Type pFillRect DXWINITIALIZED; @@ -474,8 +474,6 @@ extern HRGN WINAPI extCreateEllipticRgnIndirect(const RECT *); extern HRGN WINAPI extCreateRectRgn(int, int, int, int); extern HRGN WINAPI extCreateRectRgnIndirect(const RECT *); extern HRGN WINAPI extCreatePolygonRgn(const POINT *, int, int); -extern int WINAPI extDrawText(HDC, LPCTSTR, int, LPRECT, UINT); -extern int WINAPI extDrawTextEx(HDC, LPTSTR, int, LPRECT, UINT, LPDRAWTEXTPARAMS); extern BOOL WINAPI extMaskBlt(HDC, int, int, int, int, HDC, int, int, HBITMAP, int, int, DWORD); extern BOOL WINAPI extSetViewportOrgEx(HDC, int, int, LPPOINT); extern BOOL WINAPI extSetViewportExtEx(HDC, int, int, LPSIZE); @@ -543,6 +541,8 @@ extern HWND WINAPI extCreateDialogParam(HINSTANCE, LPCSTR, HWND, DLGPROC, LPARAM extern HWND WINAPI extCreateWindowExA(DWORD, LPCTSTR, LPCTSTR, DWORD, int, int, int, int, HWND, HMENU, HINSTANCE, LPVOID); extern HWND WINAPI extCreateWindowExW(DWORD, LPCWSTR, LPCWSTR, DWORD, int, int, int, int, HWND, HMENU, HINSTANCE, LPVOID); extern LRESULT WINAPI extDefWindowProc(HWND, UINT, WPARAM, LPARAM); +extern int WINAPI extDrawTextA(HDC, LPCTSTR, int, LPRECT, UINT); +extern int WINAPI extDrawTextExA(HDC, LPTSTR, int, LPRECT, UINT, LPDRAWTEXTPARAMS); extern BOOL WINAPI extEndPaint(HWND, const PAINTSTRUCT *); extern BOOL WINAPI extDDEndPaint(HWND, const PAINTSTRUCT *); extern LONG WINAPI extEnumDisplaySettings(LPCTSTR, DWORD, DEVMODE *); diff --git a/dll/user32.cpp b/dll/user32.cpp index 2428eef..72fae92 100644 --- a/dll/user32.cpp +++ b/dll/user32.cpp @@ -16,7 +16,7 @@ static HookEntry_Type Hooks[]={ //{"GetWindowPlacement", (FARPROC)NULL, (FARPROC *)&pGetWindowPlacement, (FARPROC)extGetWindowPlacement}, //{"SetWindowPlacement", (FARPROC)NULL, (FARPROC *)&pSetWindowPlacement, (FARPROC)extSetWindowPlacement}, {"ChangeDisplaySettingsA", (FARPROC)ChangeDisplaySettingsA, (FARPROC *)&pChangeDisplaySettingsA, (FARPROC)extChangeDisplaySettingsA}, - {"ChangeDisplaySettingsExA", (FARPROC)NULL, (FARPROC *)&pChangeDisplaySettingsExA, (FARPROC)extChangeDisplaySettingsExA}, + {"ChangeDisplaySettingsExA", (FARPROC)ChangeDisplaySettingsExA, (FARPROC *)&pChangeDisplaySettingsExA, (FARPROC)extChangeDisplaySettingsExA}, {"ChangeDisplaySettingsW", (FARPROC)NULL, (FARPROC *)&pChangeDisplaySettingsW, (FARPROC)extChangeDisplaySettingsW}, // ref. by Knights of Honor {"ChangeDisplaySettingsExW", (FARPROC)NULL, (FARPROC *)&pChangeDisplaySettingsExW, (FARPROC)extChangeDisplaySettingsExW}, {"ShowCursor", (FARPROC)ShowCursor, (FARPROC *)&pShowCursor, (FARPROC)extShowCursor}, @@ -36,6 +36,8 @@ static HookEntry_Type Hooks[]={ {"GetSystemMetrics", (FARPROC)GetSystemMetrics, (FARPROC *)&pGetSystemMetrics, (FARPROC)extGetSystemMetrics}, {"GetDesktopWindow", (FARPROC)GetDesktopWindow, (FARPROC *)&pGetDesktopWindow, (FARPROC)extGetDesktopWindow}, {"TabbedTextOutA", (FARPROC)TabbedTextOutA, (FARPROC *)&pTabbedTextOutA, (FARPROC)extTabbedTextOutA}, + {"DrawTextA", (FARPROC)DrawTextA, (FARPROC *)&pDrawText, (FARPROC)extDrawTextA}, + {"DrawTextExA", (FARPROC)DrawTextExA, (FARPROC *)&pDrawTextEx, (FARPROC)extDrawTextExA}, {"CloseWindow", (FARPROC)NULL, (FARPROC *)&pCloseWindow, (FARPROC)extCloseWindow}, {"DestroyWindow", (FARPROC)NULL, (FARPROC *)&pDestroyWindow, (FARPROC)extDestroyWindow}, {"SetSysColors", (FARPROC)NULL, (FARPROC *)&pSetSysColors, (FARPROC)extSetSysColors}, @@ -223,11 +225,8 @@ extern GetDC_Type pGetDC; extern ReleaseDC_Type pReleaseDC; extern DEVMODE *pSetDevMode; //extern void FixWindowFrame(HWND); -extern LRESULT CALLBACK extChildWindowProc(HWND, UINT, WPARAM, LPARAM); extern HRESULT WINAPI sBlt(char *, LPDIRECTDRAWSURFACE, LPRECT, LPDIRECTDRAWSURFACE, LPRECT, DWORD, LPDDBLTFX, BOOL); -extern INT_PTR CALLBACK extDialogWindowProc(HWND, UINT, WPARAM, LPARAM); - LONG WINAPI MyChangeDisplaySettings(char *fname, BOOL WideChar, void *lpDevMode, DWORD dwflags) { HRESULT res; @@ -589,7 +588,11 @@ LONG WINAPI extSetWindowLong(HWND hwnd, int nIndex, LONG dwNewLong) // end of GPL fix OldProc = (WNDPROC)(*pGetWindowLong)(hwnd, GWL_WNDPROC); - if(OldProc==extWindowProc) OldProc=WhndGetWindowProc(hwnd); + // v2.02.70 fix + if((OldProc==extWindowProc) || + (OldProc==extChildWindowProc)|| + (OldProc==extDialogWindowProc)) + OldProc=WhndGetWindowProc(hwnd); WhndStackPush(hwnd, (WNDPROC)dwNewLong); res=(LONG)OldProc; SetLastError(0); @@ -854,8 +857,12 @@ BOOL WINAPI extClientToScreen(HWND hwnd, LPPOINT lppoint) OutTraceB("ClientToScreen: hwnd=%x hWnd=%x FullScreen=%x point=(%d,%d)\n", hwnd, dxw.GethWnd(), dxw.IsFullScreen(), lppoint->x, lppoint->y); if (lppoint && dxw.IsFullScreen()){ - *lppoint = dxw.AddCoordinates(*lppoint, dxw.ClientOffset(hwnd)); - OutTraceB("ClientToScreen: FIXED point=(%d,%d)\n", lppoint->x, lppoint->y); + // optimization: in fullscreen mode, coordinate conversion for the desktop window + // should always keep the same values inaltered + if(hwnd != dxw.GethWnd()){ + *lppoint = dxw.AddCoordinates(*lppoint, dxw.ClientOffset(hwnd)); + OutTraceB("ClientToScreen: FIXED point=(%d,%d)\n", lppoint->x, lppoint->y); + } res=TRUE; } else { @@ -874,8 +881,12 @@ BOOL WINAPI extScreenToClient(HWND hwnd, LPPOINT lppoint) if (lppoint && (lppoint->x == -32000) && (lppoint->y == -32000)) return 1; if (lppoint && dxw.IsFullScreen()){ - *lppoint = dxw.SubCoordinates(*lppoint, dxw.ClientOffset(hwnd)); - OutTraceB("ScreenToClient: FIXED point=(%d,%d)\n", lppoint->x, lppoint->y); + // optimization: in fullscreen mode, coordinate conversion for the desktop window + // should always keep the same values inaltered + if(hwnd != dxw.GethWnd()){ + *lppoint = dxw.SubCoordinates(*lppoint, dxw.ClientOffset(hwnd)); + OutTraceB("ScreenToClient: FIXED point=(%d,%d)\n", lppoint->x, lppoint->y); + } res=TRUE; } else { @@ -1071,7 +1082,7 @@ static HWND WINAPI extCreateWindowCommon( HINSTANCE hInstance, LPVOID lpParam) { - HWND wndh; + HWND hwnd; WNDPROC pWindowProc; BOOL isValidHandle=TRUE; @@ -1171,11 +1182,11 @@ static HWND WINAPI extCreateWindowCommon( if(!dxw.IsFullScreen()){ // v2.1.63: needed for "Monster Truck Madness" if(WideChar) - wndh= (*pCreateWindowExW)(dwExStyle, (LPCWSTR)lpClassName, (LPCWSTR)lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); + hwnd= (*pCreateWindowExW)(dwExStyle, (LPCWSTR)lpClassName, (LPCWSTR)lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); else - wndh= (*pCreateWindowExA)(dwExStyle, (LPCSTR)lpClassName, (LPCSTR)lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); - OutTraceDW("%s: windowed mode ret=%x\n", ApiName, wndh); - return wndh; + hwnd= (*pCreateWindowExA)(dwExStyle, (LPCSTR)lpClassName, (LPCSTR)lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); + OutTraceDW("%s: windowed mode ret=%x\n", ApiName, hwnd); + return hwnd; } // tested on Gangsters: coordinates must be window-relative!!! @@ -1197,43 +1208,51 @@ static HWND WINAPI extCreateWindowCommon( ApiName, x, y, nWidth, nHeight, dwStyle, ExplainStyle(dwStyle), dwExStyle, ExplainExStyle(dwExStyle)); if(WideChar) - wndh= (*pCreateWindowExW)(dwExStyle, (LPCWSTR)lpClassName, (LPCWSTR)lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); + hwnd= (*pCreateWindowExW)(dwExStyle, (LPCWSTR)lpClassName, (LPCWSTR)lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); else - wndh= (*pCreateWindowExA)(dwExStyle, (LPCSTR)lpClassName, (LPCSTR)lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); - if (wndh==(HWND)NULL){ + hwnd= (*pCreateWindowExA)(dwExStyle, (LPCSTR)lpClassName, (LPCSTR)lpWindowName, dwStyle, x, y, nWidth, nHeight, hWndParent, hMenu, hInstance, lpParam); + if (hwnd==(HWND)NULL){ OutTraceE("%s: ERROR err=%d Style=%x(%s) ExStyle=%x\n", ApiName, GetLastError(), dwStyle, ExplainStyle(dwStyle), dwExStyle); - return wndh; + return hwnd; } if ((!isValidHandle) && dxw.IsFullScreen()){ - dxw.SethWnd(wndh); + dxw.SethWnd(hwnd); extern void AdjustWindowPos(HWND, DWORD, DWORD); - (*pSetWindowLong)(wndh, GWL_STYLE, (dxw.dwFlags2 & MODALSTYLE) ? 0 : WS_OVERLAPPEDWINDOW); - (*pSetWindowLong)(wndh, GWL_EXSTYLE, 0); - OutTraceDW("%s: hwnd=%x, set style=WS_OVERLAPPEDWINDOW extstyle=0\n", ApiName, wndh); - AdjustWindowPos(wndh, nWidth, nHeight); - (*pShowWindow)(wndh, SW_SHOWNORMAL); + (*pSetWindowLong)(hwnd, GWL_STYLE, (dxw.dwFlags2 & MODALSTYLE) ? 0 : WS_OVERLAPPEDWINDOW); + (*pSetWindowLong)(hwnd, GWL_EXSTYLE, 0); + OutTraceDW("%s: hwnd=%x, set style=WS_OVERLAPPEDWINDOW extstyle=0\n", ApiName, hwnd); + AdjustWindowPos(hwnd, nWidth, nHeight); + (*pShowWindow)(hwnd, SW_SHOWNORMAL); } //if ((dxw.dwFlags1 & FIXWINFRAME) && !(dwStyle & WS_CHILD)) - if ((dxw.dwFlags1 & FIXWINFRAME) && !(dwStyle & WS_CHILD) && dxw.IsDesktop(wndh)) - dxw.FixWindowFrame(wndh); + if ((dxw.dwFlags1 & FIXWINFRAME) && !(dwStyle & WS_CHILD) && dxw.IsDesktop(hwnd)) + dxw.FixWindowFrame(hwnd); // to do: handle inner child, and leave dialogue & modal child alone!!! if ((dwStyle & WS_CHILD) && (dxw.dwFlags1 & HOOKCHILDWIN)){ + // child window inherit the father's windproc, so if it's redirected to + // a hooker (either extWindowProc or extChildWindowProc) you have to retrieve + // the correct value (WhndGetWindowProc) before saving it (WhndStackPush). long res; - pWindowProc = (WNDPROC)(*pGetWindowLong)(wndh, GWL_WNDPROC); - if((pWindowProc != extWindowProc) && (pWindowProc != extChildWindowProc)){ // avoid recursions - OutTraceDW("Hooking CHILD wndh=%x WindowProc %x->%x\n", wndh, pWindowProc, extChildWindowProc); - res=(*pSetWindowLong)(wndh, GWL_WNDPROC, (LONG)extChildWindowProc); - WhndStackPush(wndh, pWindowProc); - if(!res) OutTraceE("%s: SetWindowLong ERROR %x\n", ApiName, GetLastError()); + pWindowProc = (WNDPROC)(*pGetWindowLong)(hwnd, GWL_WNDPROC); + if((pWindowProc == extWindowProc) || + (pWindowProc == extChildWindowProc) || + (pWindowProc == extDialogWindowProc)){ // avoid recursions + HWND Father; + Father=GetParent(hwnd); + pWindowProc=WhndGetWindowProc(Father); } + OutTraceDW("Hooking CHILD hwnd=%x father WindowProc %x->%x\n", hwnd, pWindowProc, extChildWindowProc); + res=(*pSetWindowLong)(hwnd, GWL_WNDPROC, (LONG)extChildWindowProc); + if(!res) OutTraceE("%s: SetWindowLong ERROR %x\n", ApiName, GetLastError()); + WhndStackPush(hwnd, pWindowProc); } - OutTraceDW("%s: ret=%x\n", ApiName, wndh); - return wndh; + OutTraceDW("%s: ret=%x\n", ApiName, hwnd); + return hwnd; } static LPCSTR ClassToStr(LPCSTR Class) @@ -1354,9 +1373,6 @@ int WINAPI extFillRect(HDC hdc, const RECT *lprc, HBRUSH hbr) return TRUE; } - // when not in fullscreen mode, just proxy the call - // better not: some games may use excessive coordinates: see "Premier Manager 98" - // if(!dxw.IsFullScreen() && !dxw.IsDesktop(WindowFromDC(hdc))) return (*pFillRect)(hdc, lprc, hbr); memcpy(&rc, lprc, sizeof(rc)); @@ -1365,12 +1381,25 @@ int WINAPI extFillRect(HDC hdc, const RECT *lprc, HBRUSH hbr) hdc=(*pGDIGetDC)(dxw.GethWnd()); } + if(!dxw.IsFullScreen()) { + // when not in fullscreen mode, just proxy the call + // but check coordinates: some games may use excessive coordinates: see "Premier Manager 98" + RECT client; + (*pGetClientRect)(WindowFromDC(hdc), &client); + if(rc.left < 0) rc.left=0; + if(rc.top < 0) rc.top=0; + if(rc.right > client.right) rc.right=client.right; + if(rc.bottom > client.bottom) rc.bottom=client.bottom; + return (*pFillRect)(hdc, &rc, hbr); + } + if(OBJ_DC == GetObjectType(hdc)){ if(rc.left < 0) rc.left = 0; if(rc.top < 0) rc.top = 0; if((DWORD)rc.right > dxw.GetScreenWidth()) rc.right = dxw.GetScreenWidth(); if((DWORD)rc.bottom > dxw.GetScreenHeight()) rc.bottom = dxw.GetScreenHeight(); dxw.MapClient(&rc); + //dxw.MapWindow(&rc); OutTraceDW("FillRect: fixed rect=(%d,%d)-(%d,%d)\n", rc.left, rc.top, rc.right, rc.bottom); } @@ -1764,7 +1793,8 @@ HDC WINAPI extDDBeginPaint(HWND hwnd, LPPAINTSTRUCT lpPaint) LPDIRECTDRAWSURFACE lpDDS; DDSURFACEDESC ddsd; res=extDirectDrawCreate(0, &lpDD, NULL); - lpDD->SetCooperativeLevel(dxw.GethWnd(), DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE); + //lpDD->SetCooperativeLevel(dxw.GethWnd(), DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE); + lpDD->SetCooperativeLevel(dxw.GethWnd(), DDSCL_NORMAL); memset((void *)&ddsd, 0, sizeof(DDSURFACEDESC)); ddsd.dwSize = sizeof(DDSURFACEDESC); ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH; @@ -2038,16 +2068,6 @@ int WINAPI extShowCursor(BOOL bShow) return ret; } -int WINAPI extDrawTextA(HDC hDC, LPCTSTR lpchText, int nCount, LPRECT lpRect, UINT uFormat) -{ - return 0; -} - -int WINAPI extDrawTextExA(HDC hDC, LPCTSTR lpchText, int cchText, LPRECT lprc, UINT dwDTFormat, LPDRAWTEXTPARAMS lpDTParams) -{ - return 0; -} - BOOL WINAPI extDrawFocusRect(HDC hDC, const RECT *lprc) { return TRUE; @@ -2097,6 +2117,43 @@ BOOL WINAPI extDestroyWindow(HWND hWnd) return res; } +BOOL gFixed; + +int WINAPI extDrawTextA(HDC hdc, LPCTSTR lpchText, int nCount, LPRECT lpRect, UINT uFormat) +{ + int ret; + OutTraceDW("DrawText: hdc=%x rect=(%d,%d)-(%d,%d) Format=%x Text=(%d)\"%s\"\n", + hdc, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, uFormat, nCount, lpchText); + + gFixed = TRUE; + if (dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hdc))){ + dxw.MapClient((RECT *)lpRect); + OutTraceDW("DrawText: fixed rect=(%d,%d)-(%d,%d)\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + } + + ret=(*pDrawText)(hdc, lpchText, nCount, lpRect, uFormat); + gFixed=FALSE; + // if nCount is zero, DrawRect returns 0 as text heigth, but this is not an error! (ref. "Imperialism II") + if(nCount && !ret) OutTraceE("DrawText: ERROR ret=%x err=%d\n", ret, GetLastError()); + return ret; +} + +int WINAPI extDrawTextExA(HDC hdc, LPTSTR lpchText, int nCount, LPRECT lpRect, UINT dwDTFormat, LPDRAWTEXTPARAMS lpDTParams) +{ + int ret; + OutTraceDW("DrawTextEx: hdc=%x rect=(%d,%d)-(%d,%d) DTFormat=%x Text=(%d)\"%s\"\n", + hdc, lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, dwDTFormat, nCount, lpchText); + + if (dxw.IsFullScreen() && (OBJ_DC == GetObjectType(hdc))){ + dxw.MapClient((RECT *)lpRect); + OutTraceDW("DrawTextEx: fixed rect=(%d,%d)-(%d,%d)\n", lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + } + + ret=(*pDrawTextEx)(hdc, lpchText, nCount, lpRect, dwDTFormat, lpDTParams); + if(!ret) OutTraceE("DrawTextEx: ERROR ret=%x err=%d\n", ret, GetLastError()); + return ret; +} + BOOL WINAPI extCloseWindow(HWND hWnd) { // from MSDN: Minimizes (but does not destroy) the specified window. @@ -2185,10 +2242,10 @@ BOOL WINAPI extSetWindowPlacement(HWND hwnd, WINDOWPLACEMENT *lpwndpl) lpwndpl->rcNormalPosition.left, lpwndpl->rcNormalPosition.top, lpwndpl->rcNormalPosition.right, lpwndpl->rcNormalPosition.bottom); switch (lpwndpl->showCmd){ - case SW_SHOW: + case SW_MAXIMIZE: if (dxw.IsFullScreen()){ - lpwndpl->showCmd = SW_MAXIMIZE; - OutTraceDW("SetWindowPlacement: forcing SW_MAXIMIZE state\n"); + lpwndpl->showCmd = SW_SHOW; + OutTraceDW("SetWindowPlacement: forcing SW_SHOW state\n"); } break; } diff --git a/host/CppUACSelfElevation.cpp b/host/CppUACSelfElevation.cpp new file mode 100644 index 0000000..9dad8dc --- /dev/null +++ b/host/CppUACSelfElevation.cpp @@ -0,0 +1,712 @@ +/****************************** Module Header ******************************\ +Module Name: CppUACSelfElevation.cpp +Project: CppUACSelfElevation +Copyright (c) Microsoft Corporation. + +User Account Control (UAC) is a new security component in Windows Vista and +newer operating systems. With UAC fully enabled, interactive administrators +normally run with least user privileges. This example demonstrates how to +check the privilege level of the current process, and how to self-elevate +the process by giving explicit consent with the Consent UI. + +This source is subject to the Microsoft Public License. +See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL. +All other rights reserved. + +THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, +EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE. +\***************************************************************************/ + +#pragma region Includes and Manifest Dependencies + +#include "stdafx.h" + +#include +#include +#include +#include +#include +#include "Resource.h" +#include + +// Enable Visual Style +#if defined _M_IX86 +#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") +#elif defined _M_IA64 +#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"") +#elif defined _M_X64 +#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") +#else +#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") +#endif +#pragma endregion + + +#pragma region "Helper Functions for Admin Privileges and Elevation Status" + +// +// FUNCTION: IsUserInAdminGroup() +// +// PURPOSE: The function checks whether the primary access token of the +// process belongs to user account that is a member of the local +// Administrators group, even if it currently is not elevated. +// +// RETURN VALUE: Returns TRUE if the primary access token of the process +// belongs to user account that is a member of the local Administrators +// group. Returns FALSE if the token does not. +// +// EXCEPTION: If this function fails, it throws a C++ DWORD exception which +// contains the Win32 error code of the failure. +// +// EXAMPLE CALL: +// try +// { +// if (IsUserInAdminGroup()) +// wprintf (L"User is a member of the Administrators group\n"); +// else +// wprintf (L"User is not a member of the Administrators group\n"); +// } +// catch (DWORD dwError) +// { +// wprintf(L"IsUserInAdminGroup failed w/err %lu\n", dwError); +// } +// +BOOL IsUserInAdminGroup() +{ + BOOL fInAdminGroup = FALSE; + DWORD dwError = ERROR_SUCCESS; + HANDLE hToken = NULL; + HANDLE hTokenToCheck = NULL; + DWORD cbSize = 0; + OSVERSIONINFO osver = { sizeof(osver) }; + + // Open the primary access token of the process for query and duplicate. + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_DUPLICATE, + &hToken)) + { + dwError = GetLastError(); + goto Cleanup; + } + + // Determine whether system is running Windows Vista or later operating + // systems (major version >= 6) because they support linked tokens, but + // previous versions (major version < 6) do not. + if (!GetVersionEx(&osver)) + { + dwError = GetLastError(); + goto Cleanup; + } + + if (osver.dwMajorVersion >= 6) + { + // Running Windows Vista or later (major version >= 6). + // Determine token type: limited, elevated, or default. + TOKEN_ELEVATION_TYPE elevType; + if (!GetTokenInformation(hToken, TokenElevationType, &elevType, + sizeof(elevType), &cbSize)) + { + dwError = GetLastError(); + goto Cleanup; + } + + // If limited, get the linked elevated token for further check. + if (TokenElevationTypeLimited == elevType) + { + if (!GetTokenInformation(hToken, TokenLinkedToken, &hTokenToCheck, + sizeof(hTokenToCheck), &cbSize)) + { + dwError = GetLastError(); + goto Cleanup; + } + } + } + + // CheckTokenMembership requires an impersonation token. If we just got a + // linked token, it already is an impersonation token. If we did not get + // a linked token, duplicate the original into an impersonation token for + // CheckTokenMembership. + if (!hTokenToCheck) + { + if (!DuplicateToken(hToken, SecurityIdentification, &hTokenToCheck)) + { + dwError = GetLastError(); + goto Cleanup; + } + } + + // Create the SID corresponding to the Administrators group. + BYTE adminSID[SECURITY_MAX_SID_SIZE]; + cbSize = sizeof(adminSID); + if (!CreateWellKnownSid(WinBuiltinAdministratorsSid, NULL, &adminSID, + &cbSize)) + { + dwError = GetLastError(); + goto Cleanup; + } + + // Check if the token to be checked contains admin SID. + // http://msdn.microsoft.com/en-us/library/aa379596(VS.85).aspx: + // To determine whether a SID is enabled in a token, that is, whether it + // has the SE_GROUP_ENABLED attribute, call CheckTokenMembership. + if (!CheckTokenMembership(hTokenToCheck, &adminSID, &fInAdminGroup)) + { + dwError = GetLastError(); + goto Cleanup; + } + +Cleanup: + // Centralized cleanup for all allocated resources. + if (hToken) + { + CloseHandle(hToken); + hToken = NULL; + } + if (hTokenToCheck) + { + CloseHandle(hTokenToCheck); + hTokenToCheck = NULL; + } + + // Throw the error if something failed in the function. + if (ERROR_SUCCESS != dwError) + { + throw dwError; + } + + return fInAdminGroup; +} + + +// +// FUNCTION: IsRunAsAdmin() +// +// PURPOSE: The function checks whether the current process is run as +// administrator. In other words, it dictates whether the primary access +// token of the process belongs to user account that is a member of the +// local Administrators group and it is elevated. +// +// RETURN VALUE: Returns TRUE if the primary access token of the process +// belongs to user account that is a member of the local Administrators +// group and it is elevated. Returns FALSE if the token does not. +// +// EXCEPTION: If this function fails, it throws a C++ DWORD exception which +// contains the Win32 error code of the failure. +// +// EXAMPLE CALL: +// try +// { +// if (IsRunAsAdmin()) +// wprintf (L"Process is run as administrator\n"); +// else +// wprintf (L"Process is not run as administrator\n"); +// } +// catch (DWORD dwError) +// { +// wprintf(L"IsRunAsAdmin failed w/err %lu\n", dwError); +// } +// +BOOL IsRunAsAdmin() +{ + BOOL fIsRunAsAdmin = FALSE; + DWORD dwError = ERROR_SUCCESS; + PSID pAdministratorsGroup = NULL; + + // Allocate and initialize a SID of the administrators group. + SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; + if (!AllocateAndInitializeSid( + &NtAuthority, + 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, + &pAdministratorsGroup)) + { + dwError = GetLastError(); + goto Cleanup; + } + + // Determine whether the SID of administrators group is enabled in + // the primary access token of the process. + if (!CheckTokenMembership(NULL, pAdministratorsGroup, &fIsRunAsAdmin)) + { + dwError = GetLastError(); + goto Cleanup; + } + +Cleanup: + // Centralized cleanup for all allocated resources. + if (pAdministratorsGroup) + { + FreeSid(pAdministratorsGroup); + pAdministratorsGroup = NULL; + } + + // Throw the error if something failed in the function. + if (ERROR_SUCCESS != dwError) + { + throw dwError; + } + + return fIsRunAsAdmin; +} + + +// +// FUNCTION: IsProcessElevated() +// +// PURPOSE: The function gets the elevation information of the current +// process. It dictates whether the process is elevated or not. Token +// elevation is only available on Windows Vista and newer operating +// systems, thus IsProcessElevated throws a C++ exception if it is called +// on systems prior to Windows Vista. It is not appropriate to use this +// function to determine whether a process is run as administartor. +// +// RETURN VALUE: Returns TRUE if the process is elevated. Returns FALSE if +// it is not. +// +// EXCEPTION: If this function fails, it throws a C++ DWORD exception +// which contains the Win32 error code of the failure. For example, if +// IsProcessElevated is called on systems prior to Windows Vista, the error +// code will be ERROR_INVALID_PARAMETER. +// +// NOTE: TOKEN_INFORMATION_CLASS provides TokenElevationType to check the +// elevation type (TokenElevationTypeDefault / TokenElevationTypeLimited / +// TokenElevationTypeFull) of the process. It is different from +// TokenElevation in that, when UAC is turned off, elevation type always +// returns TokenElevationTypeDefault even though the process is elevated +// (Integrity Level == High). In other words, it is not safe to say if the +// process is elevated based on elevation type. Instead, we should use +// TokenElevation. +// +// EXAMPLE CALL: +// try +// { +// if (IsProcessElevated()) +// wprintf (L"Process is elevated\n"); +// else +// wprintf (L"Process is not elevated\n"); +// } +// catch (DWORD dwError) +// { +// wprintf(L"IsProcessElevated failed w/err %lu\n", dwError); +// } +// +BOOL IsProcessElevated() +{ + BOOL fIsElevated = FALSE; + DWORD dwError = ERROR_SUCCESS; + HANDLE hToken = NULL; + + // Open the primary access token of the process with TOKEN_QUERY. + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) + { + dwError = GetLastError(); + goto Cleanup; + } + + // Retrieve token elevation information. + TOKEN_ELEVATION elevation; + DWORD dwSize; + if (!GetTokenInformation(hToken, TokenElevation, &elevation, + sizeof(elevation), &dwSize)) + { + // When the process is run on operating systems prior to Windows + // Vista, GetTokenInformation returns FALSE with the + // ERROR_INVALID_PARAMETER error code because TokenElevation is + // not supported on those operating systems. + dwError = GetLastError(); + goto Cleanup; + } + + fIsElevated = elevation.TokenIsElevated; + +Cleanup: + // Centralized cleanup for all allocated resources. + if (hToken) + { + CloseHandle(hToken); + hToken = NULL; + } + + // Throw the error if something failed in the function. + if (ERROR_SUCCESS != dwError) + { + throw dwError; + } + + return fIsElevated; +} + + +// +// FUNCTION: GetProcessIntegrityLevel() +// +// PURPOSE: The function gets the integrity level of the current process. +// Integrity level is only available on Windows Vista and newer operating +// systems, thus GetProcessIntegrityLevel throws a C++ exception if it is +// called on systems prior to Windows Vista. +// +// RETURN VALUE: Returns the integrity level of the current process. It is +// usually one of these values: +// +// SECURITY_MANDATORY_UNTRUSTED_RID (SID: S-1-16-0x0) +// Means untrusted level. It is used by processes started by the +// Anonymous group. Blocks most write access. +// +// SECURITY_MANDATORY_LOW_RID (SID: S-1-16-0x1000) +// Means low integrity level. It is used by Protected Mode Internet +// Explorer. Blocks write acess to most objects (such as files and +// registry keys) on the system. +// +// SECURITY_MANDATORY_MEDIUM_RID (SID: S-1-16-0x2000) +// Means medium integrity level. It is used by normal applications +// being launched while UAC is enabled. +// +// SECURITY_MANDATORY_HIGH_RID (SID: S-1-16-0x3000) +// Means high integrity level. It is used by administrative applications +// launched through elevation when UAC is enabled, or normal +// applications if UAC is disabled and the user is an administrator. +// +// SECURITY_MANDATORY_SYSTEM_RID (SID: S-1-16-0x4000) +// Means system integrity level. It is used by services and other +// system-level applications (such as Wininit, Winlogon, Smss, etc.) +// +// EXCEPTION: If this function fails, it throws a C++ DWORD exception +// which contains the Win32 error code of the failure. For example, if +// GetProcessIntegrityLevel is called on systems prior to Windows Vista, +// the error code will be ERROR_INVALID_PARAMETER. +// +// EXAMPLE CALL: +// try +// { +// DWORD dwIntegrityLevel = GetProcessIntegrityLevel(); +// } +// catch (DWORD dwError) +// { +// wprintf(L"GetProcessIntegrityLevel failed w/err %lu\n", dwError); +// } +// +DWORD GetProcessIntegrityLevel() +{ + DWORD dwIntegrityLevel = 0; + DWORD dwError = ERROR_SUCCESS; + HANDLE hToken = NULL; + DWORD cbTokenIL = 0; + PTOKEN_MANDATORY_LABEL pTokenIL = NULL; + + // Open the primary access token of the process with TOKEN_QUERY. + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) + { + dwError = GetLastError(); + goto Cleanup; + } + + // Query the size of the token integrity level information. Note that + // we expect a FALSE result and the last error ERROR_INSUFFICIENT_BUFFER + // from GetTokenInformation because we have given it a NULL buffer. On + // exit cbTokenIL will tell the size of the integrity level information. + if (!GetTokenInformation(hToken, TokenIntegrityLevel, NULL, 0, &cbTokenIL)) + { + if (ERROR_INSUFFICIENT_BUFFER != GetLastError()) + { + // When the process is run on operating systems prior to Windows + // Vista, GetTokenInformation returns FALSE with the + // ERROR_INVALID_PARAMETER error code because TokenElevation + // is not supported on those operating systems. + dwError = GetLastError(); + goto Cleanup; + } + } + + // Now we allocate a buffer for the integrity level information. + pTokenIL = (TOKEN_MANDATORY_LABEL *)LocalAlloc(LPTR, cbTokenIL); + if (pTokenIL == NULL) + { + dwError = GetLastError(); + goto Cleanup; + } + + // Retrieve token integrity level information. + if (!GetTokenInformation(hToken, TokenIntegrityLevel, pTokenIL, + cbTokenIL, &cbTokenIL)) + { + dwError = GetLastError(); + goto Cleanup; + } + + // Integrity Level SIDs are in the form of S-1-16-0xXXXX. (e.g. + // S-1-16-0x1000 stands for low integrity level SID). There is one and + // only one subauthority. + dwIntegrityLevel = *GetSidSubAuthority(pTokenIL->Label.Sid, 0); + +Cleanup: + // Centralized cleanup for all allocated resources. + if (hToken) + { + CloseHandle(hToken); + hToken = NULL; + } + if (pTokenIL) + { + LocalFree(pTokenIL); + pTokenIL = NULL; + cbTokenIL = 0; + } + + // Throw the error if something failed in the function. + if (ERROR_SUCCESS != dwError) + { + throw dwError; + } + + return dwIntegrityLevel; +} + +#pragma endregion + + +// +// FUNCTION: ReportError(LPWSTR, DWORD) +// +// PURPOSE: Display an error dialog for the failure of a certain function. +// +// PARAMETERS: +// * pszFunction - the name of the function that failed. +// * dwError - the Win32 error code. Its default value is the calling +// thread's last-error code value. +// +// NOTE: The failing function must be immediately followed by the call of +// ReportError if you do not explicitly specify the dwError parameter of +// ReportError. This is to ensure that the calling thread's last-error code +// value is not overwritten by any calls of API between the failing +// function and ReportError. +// +void ReportError(LPCWSTR pszFunction, DWORD dwError = GetLastError()) +{ + char szMessage[200]; + if (SUCCEEDED(StringCchPrintf(szMessage, ARRAYSIZE(szMessage), + "%s failed w/err 0x%08lx", pszFunction, dwError))) + { + MessageBox(NULL, szMessage, "Error", MB_ICONERROR); + } +} + +#if 0 +// +// FUNCTION: OnInitDialog(HWND, HWND, LPARAM) +// +// PURPOSE: Process the WM_INITDIALOG message. Check and display the +// "run as administrator" status, the elevation information, and the +// integrity level of the current process. +// +BOOL OnInitDialog(HWND hWnd, HWND hwndFocus, LPARAM lParam) +{ + // Get and display whether the primary access token of the process + // belongs to user account that is a member of the local Administrators + // group even if it currently is not elevated (IsUserInAdminGroup). + HWND hInAdminGroupLabel = GetDlgItem(hWnd, IDC_STATIC_INADMINGROUP); + try + { + BOOL const fInAdminGroup = IsUserInAdminGroup(); + SetWindowText(hInAdminGroupLabel, fInAdminGroup ? L"True" : L"False"); + } + catch (DWORD dwError) + { + SetWindowText(hInAdminGroupLabel, L"N/A"); + ReportError(L"IsUserInAdminGroup", dwError); + } + + // Get and display whether the process is run as administrator or not + // (IsRunAsAdmin). + HWND hIsRunAsAdminLabel = GetDlgItem(hWnd, IDC_STATIC_ISRUNASADMIN); + try + { + BOOL const fIsRunAsAdmin = IsRunAsAdmin(); + SetWindowText(hIsRunAsAdminLabel, fIsRunAsAdmin ? L"True" : L"False"); + } + catch (DWORD dwError) + { + SetWindowText(hIsRunAsAdminLabel, L"N/A"); + ReportError(L"IsRunAsAdmin", dwError); + } + + // Get and display the process elevation information (IsProcessElevated) + // and integrity level (GetProcessIntegrityLevel). The information is not + // available on operating systems prior to Windows Vista. + + HWND hIsElevatedLabel = GetDlgItem(hWnd, IDC_STATIC_ISELEVATED); + HWND hILLabel = GetDlgItem(hWnd, IDC_STATIC_IL); + + OSVERSIONINFO osver = { sizeof(osver) }; + if (GetVersionEx(&osver) && osver.dwMajorVersion >= 6) + { + // Running Windows Vista or later (major version >= 6). + + try + { + // Get and display the process elevation information. + BOOL const fIsElevated = IsProcessElevated(); + SetWindowText(hIsElevatedLabel, fIsElevated ? L"True" : L"False"); + + // Update the Self-elevate button to show the UAC shield icon on + // the UI if the process is not elevated. The + // Button_SetElevationRequiredState macro (declared in Commctrl.h) + // is used to show or hide the shield icon in a button. You can + // also get the shield directly as an icon by calling + // SHGetStockIconInfo with SIID_SHIELD as the parameter. + HWND hElevateBtn = GetDlgItem(hWnd, IDC_BUTTON_ELEVATE); + Button_SetElevationRequiredState(hElevateBtn, !fIsElevated); + } + catch (DWORD dwError) + { + SetWindowText(hIsElevatedLabel, L"N/A"); + ReportError(L"IsProcessElevated", dwError); + } + + try + { + // Get and display the process integrity level. + DWORD const dwIntegrityLevel = GetProcessIntegrityLevel(); + switch (dwIntegrityLevel) + { + case SECURITY_MANDATORY_UNTRUSTED_RID: SetWindowText(hILLabel, L"Untrusted"); break; + case SECURITY_MANDATORY_LOW_RID: SetWindowText(hILLabel, L"Low"); break; + case SECURITY_MANDATORY_MEDIUM_RID: SetWindowText(hILLabel, L"Medium"); break; + case SECURITY_MANDATORY_HIGH_RID: SetWindowText(hILLabel, L"High"); break; + case SECURITY_MANDATORY_SYSTEM_RID: SetWindowText(hILLabel, L"System"); break; + default: SetWindowText(hILLabel, L"Unknown"); break; + } + } + catch (DWORD dwError) + { + SetWindowText(hILLabel, L"N/A"); + ReportError(L"GetProcessIntegrityLevel", dwError); + } + } + else + { + SetWindowText(hIsElevatedLabel, L"N/A"); + SetWindowText(hILLabel, L"N/A"); + } + + return TRUE; +} + + +// +// FUNCTION: OnCommand(HWND, int, HWND, UINT) +// +// PURPOSE: Process the WM_COMMAND message +// +void OnCommand(HWND hWnd, int id, HWND hwndCtl, UINT codeNotify) +{ + switch (id) + { + case IDC_BUTTON_ELEVATE: + { + // Check the current process's "run as administrator" status. + BOOL fIsRunAsAdmin; + try + { + fIsRunAsAdmin = IsRunAsAdmin(); + } + catch (DWORD dwError) + { + ReportError(L"IsRunAsAdmin", dwError); + break; + } + + // Elevate the process if it is not run as administrator. + if (!fIsRunAsAdmin) + { + wchar_t szPath[MAX_PATH]; + if (GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath))) + { + // Launch itself as administrator. + SHELLEXECUTEINFO sei = { sizeof(sei) }; + sei.lpVerb = L"runas"; + sei.lpFile = szPath; + sei.hwnd = hWnd; + sei.nShow = SW_NORMAL; + + if (!ShellExecuteEx(&sei)) + { + DWORD dwError = GetLastError(); + if (dwError == ERROR_CANCELLED) + { + // The user refused the elevation. + // Do nothing ... + } + } + else + { + EndDialog(hWnd, TRUE); // Quit itself + } + } + } + else + { + MessageBox(hWnd, L"The process is running as administrator", L"UAC", MB_OK); + } + } + break; + + case IDOK: + case IDCANCEL: + EndDialog(hWnd, 0); + break; + } +} + + +// +// FUNCTION: OnClose(HWND) +// +// PURPOSE: Process the WM_CLOSE message +// +void OnClose(HWND hWnd) +{ + EndDialog(hWnd, 0); +} + + +// +// FUNCTION: DialogProc(HWND, UINT, WPARAM, LPARAM) +// +// PURPOSE: Processes messages for the main dialog. +// +INT_PTR CALLBACK DialogProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + // Handle the WM_INITDIALOG message in OnInitDialog + HANDLE_MSG (hWnd, WM_INITDIALOG, OnInitDialog); + + // Handle the WM_COMMAND message in OnCommand + HANDLE_MSG (hWnd, WM_COMMAND, OnCommand); + + // Handle the WM_CLOSE message in OnClose + HANDLE_MSG (hWnd, WM_CLOSE, OnClose); + + default: + return FALSE; + } + return 0; +} + + +// +// FUNCTION: wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int) +// +// PURPOSE: The entry point of the application. +// +int APIENTRY wWinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPWSTR lpCmdLine, + int nCmdShow) +{ + return DialogBox(hInstance, MAKEINTRESOURCE(IDD_MAINDIALOG), NULL, DialogProc); +} + +#endif \ No newline at end of file diff --git a/host/MainFrm.cpp b/host/MainFrm.cpp index f81a617..927c448 100644 --- a/host/MainFrm.cpp +++ b/host/MainFrm.cpp @@ -46,13 +46,15 @@ END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CMainFrame class constructor / destructor +HANDLE GlobalLocker; CMainFrame::CMainFrame() { // form constructor starts the service thread responsible to mantain a fixed screen settings // see above .... // duplicate activation check - if(CreateSemaphore(NULL, 0, 1, "DxWnd LOCKER")==NULL){ + GlobalLocker=CreateSemaphore(NULL, 0, 1, "DxWnd LOCKER"); + if(GlobalLocker==NULL){ MessageBoxEx(0, "CreateSemaphore FAILED.\nExiting.", "Warning", MB_OK | MB_ICONEXCLAMATION, NULL); return; } @@ -69,6 +71,9 @@ CMainFrame::~CMainFrame() GetCurrentDirectory(MAX_PATH, InitPath); strcat_s(InitPath, sizeof(InitPath), "\\dxwnd.ini"); + // when in icon tray, skip... + if (!cx || !cy) return; + // adjust client win coordinates RECT rect; rect.top = y; @@ -113,6 +118,8 @@ BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) // keep window inside desktop boundaries ::GetWindowRect(::GetDesktopWindow(), &DesktopRect); + if(cs.cx < 320) cs.cx = 320; + if(cs.cy < 200) cs.cy = 200; if(cs.x < DesktopRect.left) cs.x = DesktopRect.left; if(cs.y < DesktopRect.top) cs.y = DesktopRect.top; if(cs.x+cs.cx > DesktopRect.right) cs.x = DesktopRect.right - cs.cx; diff --git a/host/Resource.h b/host/Resource.h index 23d957d..a2b451b 100644 --- a/host/Resource.h +++ b/host/Resource.h @@ -264,7 +264,7 @@ #define _APS_3D_CONTROLS 1 #define _APS_NEXT_RESOURCE_VALUE 159 #define _APS_NEXT_COMMAND_VALUE 32830 -#define _APS_NEXT_CONTROL_VALUE 1100 +#define _APS_NEXT_CONTROL_VALUE 1172 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif diff --git a/host/dxwndhost.cpp b/host/dxwndhost.cpp index ae5e66d..817acac 100644 --- a/host/dxwndhost.cpp +++ b/host/dxwndhost.cpp @@ -127,6 +127,51 @@ BOOL CDxwndhostApp::InitInstance() m_pMainWnd->ShowWindow(SW_SHOW); m_pMainWnd->UpdateWindow(); + extern BOOL IsProcessElevated(); + extern BOOL IsUserInAdminGroup(); + OSVERSIONINFO osver = { sizeof(osver) }; + if (GetVersionEx(&osver) && osver.dwMajorVersion >= 6) + { + BOOL const fInAdminGroup = IsUserInAdminGroup(); + if(!fInAdminGroup) return TRUE; + + // Get and display the process elevation information. + BOOL const fIsElevated = IsProcessElevated(); + BOOL MustRestart; + if(fIsElevated) return TRUE; + MustRestart=MessageBoxEx(0, + "Administrator capability is missing.\n" + "It could be required to handle some programs.\n" + "Do you want to acquire it?", + "Warning", MB_OKCANCEL | MB_ICONQUESTION, NULL); + + if(MustRestart==IDOK){ + extern HANDLE GlobalLocker; + CloseHandle(GlobalLocker); + char szPath[MAX_PATH]; + if (GetModuleFileName(NULL, szPath, ARRAYSIZE(szPath))) + { + // Launch itself as administrator. + SHELLEXECUTEINFO sei = { sizeof(sei) }; + sei.lpVerb = "runas"; + sei.lpFile = szPath; + //sei.hwnd = (HWND)this->GetMainWnd(); + sei.hwnd = (HWND)NULL; // set to NULL to force the confirmation dialog on top of everything... + sei.nShow = SW_NORMAL; + if (!ShellExecuteEx(&sei)){ + DWORD dwError = GetLastError(); + if (dwError == ERROR_CANCELLED){ + // The user refused the elevation. + // Do nothing ... + } + } + else{ + exit(0); // Quit itself + } + } + } + } + return TRUE; } diff --git a/host/dxwndhost.vs2008.suo b/host/dxwndhost.vs2008.suo index 1f8d2bf..4b1c536 100644 Binary files a/host/dxwndhost.vs2008.suo and b/host/dxwndhost.vs2008.suo differ diff --git a/host/dxwndhost.vs2008.vcproj b/host/dxwndhost.vs2008.vcproj index 21aad64..a3532ac 100644 --- a/host/dxwndhost.vs2008.vcproj +++ b/host/dxwndhost.vs2008.vcproj @@ -219,6 +219,10 @@ Name="Source Files" Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" > + +