Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

621 lines
16 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. extern "C"
  4. {
  5. #include <stdexts.h>
  6. #include <winuserp.h>
  7. #include <wowuserp.h>
  8. #include <psapi.h>
  9. };
  10. typedef struct _LARGE_UNICODE_STRING {
  11. ULONG Length;
  12. ULONG MaximumLength : 31;
  13. ULONG bAnsi : 1;
  14. void *Buffer; // kernel-sized pointer
  15. } LARGE_UNICODE_STRING, *PLARGE_UNICODE_STRING;
  16. typedef struct tagWND : public WW
  17. {
  18. tagWND* spwndNext;
  19. tagWND* spwndPrev;
  20. tagWND* spwndParent;
  21. tagWND* spwndChild;
  22. tagWND* spwndOwner;
  23. RECT rcWindow;
  24. RECT rcClient;
  25. WNDPROC lpfnWndProc;
  26. void* pcls;
  27. HRGN hrgnUpdate; // kernel-sized pointer
  28. void* ppropList;
  29. void* pSBInfo;
  30. HMENU spmenuSys;
  31. HMENU spmenu;
  32. HRGN hrgnClip;
  33. LARGE_UNICODE_STRING strName;
  34. int cbWndExtra;
  35. void* spwndLastActive;
  36. void* hImc; // kernel-sized pointer
  37. void* dwUserData; // kernel-sized pointer
  38. void* pActCtx;
  39. } WND, *PWND;
  40. BOOL CALLBACK PropEnumProc(HWND hwnd, LPCSTR lpszString, HANDLE hData)
  41. {
  42. if (IS_INTRESOURCE(lpszString))
  43. {
  44. Print("Prop 0x%04x = 0x%08x\n", lpszString, hData);
  45. }
  46. else
  47. {
  48. Print("Prop \"%s\" = 0x%08x\n", lpszString, hData);
  49. }
  50. return TRUE;
  51. }
  52. void DumpWindowBytes(HWND hwnd)
  53. {
  54. PWND pwnd = (PWND)GetWindowLongPtr(hwnd, GWLP_WOWWORDS);
  55. if (pwnd)
  56. {
  57. Print("cbWndExtra=%d\n", pwnd->cbWndExtra);
  58. // USER tries to hide GetWindowLong from out-of-process apps
  59. // so we have to grovel it manually.
  60. LONG_PTR *rglp = (LONG_PTR*)(pwnd+1);
  61. for (int i = 0; i < pwnd->cbWndExtra; i += sizeof(LONG_PTR))
  62. {
  63. LONG_PTR lp = *(LONG_PTR*)((LPBYTE)(pwnd+1) + i);
  64. Print("%8d = 0x%p\n", i, lp);
  65. }
  66. }
  67. Print("UserData = 0x%p\n", pwnd->dwUserData);
  68. }
  69. void DumpMiscWindowInfo(HWND hwnd, char *szBuf)
  70. {
  71. Print("\n"
  72. "GetClipboardOwner() = 0x%p\n", GetClipboardOwner());
  73. Print("GetClipboardViewer() = 0x%p\n", GetClipboardViewer());
  74. Print("GetOpenClipboardWindow() = 0x%p\n", GetOpenClipboardWindow());
  75. Print("GetActiveWindow() = 0x%p\n", GetActiveWindow());
  76. Print("GetFocus() = 0x%p\n", GetFocus());
  77. Print("GetCapture() = 0x%p\n", GetCapture());
  78. Print("GetForegroundWindow() = 0x%p\n", GetForegroundWindow());
  79. Print("GetWindowContextHelpId() = 0x%p\n", GetWindowContextHelpId(hwnd));
  80. Print("GetDesktopWindow() = 0x%p\n", GetDesktopWindow());
  81. Print("GetLastActivePopup() = 0x%p\n", GetLastActivePopup(hwnd));
  82. if (GetWindowModuleFileNameA(hwnd, szBuf, MAX_PATH))
  83. {
  84. Print("GetWindowModuleFileName()= %s\n", szBuf);
  85. }
  86. DWORD pid;
  87. if (GetWindowThreadProcessId(hwnd, &pid))
  88. {
  89. HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
  90. if (h)
  91. {
  92. if (GetModuleFileNameExA(h, NULL, szBuf, MAX_PATH))
  93. {
  94. Print("Process = %s\n", szBuf);
  95. }
  96. CloseHandle(h);
  97. }
  98. }
  99. }
  100. extern "C" BOOL Ihwnd(DWORD dwOpts,
  101. LPVOID pArg )
  102. {
  103. HWND hwnd = (HWND)pArg;
  104. char szBuf[MAX_PATH];
  105. RECT rc;
  106. if (hwnd == 0)
  107. hwnd = GetDesktopWindow();
  108. Print("Window 0x%08x ", hwnd);
  109. if (!IsWindow(hwnd))
  110. {
  111. Print("*** NOT A WINDOW HANDLE\n");
  112. return TRUE;
  113. }
  114. if (dwOpts & OFLAG(m))
  115. {
  116. DumpMiscWindowInfo(hwnd, szBuf);
  117. return TRUE;
  118. }
  119. GetWindowTextA(hwnd, szBuf, ARRAYSIZE(szBuf));
  120. Print("\"%s\" ", szBuf);
  121. GetClassNameA(hwnd, szBuf, ARRAYSIZE(szBuf));
  122. Print("(%s)", szBuf);
  123. if (IsWindowUnicode(hwnd)) {
  124. Print(" UNICODE\n");
  125. } else {
  126. Print(" ANSI\n");
  127. }
  128. if ( dwOpts & OFLAG(p) )
  129. {
  130. EnumPropsA(hwnd, PropEnumProc);
  131. Print("End of property list\n");
  132. return TRUE;
  133. }
  134. if ( dwOpts & OFLAG(b) )
  135. {
  136. DumpWindowBytes(hwnd);
  137. return TRUE;
  138. }
  139. Print(" N=0x%08x C=0x%08x P=0x%08x O=0x%08x\n",
  140. GetWindow(hwnd, GW_HWNDNEXT),
  141. GetWindow(hwnd, GW_CHILD),
  142. GetAncestor(hwnd, GA_PARENT),
  143. GetWindow(hwnd, GW_OWNER));
  144. GetWindowRect(hwnd, &rc);
  145. Print(" W=(%d,%d)-(%d,%d) %dx%d ",
  146. rc.left, rc.top,
  147. rc.right, rc.bottom,
  148. rc.right - rc.left,
  149. rc.bottom - rc.top);
  150. GetClientRect(hwnd, &rc);
  151. Print(" C=(%d,%d)-(%d,%d) %dx%d\n",
  152. rc.left, rc.top,
  153. rc.right, rc.bottom,
  154. rc.right - rc.left,
  155. rc.bottom - rc.top);
  156. DWORD dwPid = 0;
  157. DWORD dwTid = GetWindowThreadProcessId(hwnd, &dwPid);
  158. Print(" pid.tid=0x%x.0x%x hinst=0x%p ", dwPid, dwTid,
  159. GetWindowLongPtr(hwnd, GWLP_HINSTANCE));
  160. // Now the evil part: Getting the wndproc...
  161. PWND pwnd = (PWND)GetWindowLongPtr(hwnd, GWLP_WOWWORDS);
  162. if (pwnd)
  163. {
  164. Print("wp=0x%p", pwnd->lpfnWndProc);
  165. }
  166. Print("\n");
  167. Print(" style-0x%08x exstyle=0x%08x\n",
  168. GetWindowLong(hwnd, GWL_STYLE),
  169. GetWindowLong(hwnd, GWL_EXSTYLE));
  170. return TRUE;
  171. }
  172. /***********************************************************************/
  173. extern "C" BOOL Ihmenu(DWORD dwOpts,
  174. LPVOID pArg )
  175. {
  176. HMENU hmenu = (HMENU)pArg;
  177. char szBuf[MAX_PATH];
  178. RECT rc;
  179. Print("Menu 0x%08x ", hmenu);
  180. if (!IsMenu(hmenu))
  181. {
  182. Print("*** NOT A MENU HANDLE\n");
  183. return TRUE;
  184. }
  185. UINT cItems = GetMenuItemCount(hmenu);
  186. Print("%d items\n", cItems);
  187. UINT uiPosDefault = GetMenuDefaultItem(hmenu, TRUE, GMDI_USEDISABLED);
  188. for (UINT ui = 0; !IsCtrlCHit() && ui < cItems; ui++)
  189. {
  190. MENUITEMINFOA mii = { 0 };
  191. mii.cbSize = sizeof(mii);
  192. mii.fMask = MIIM_DATA | MIIM_FTYPE | MIIM_ID | MIIM_STATE |
  193. MIIM_STRING | MIIM_SUBMENU;
  194. mii.dwTypeData = szBuf;
  195. mii.cch = ARRAYSIZE(szBuf);
  196. if (GetMenuItemInfoA(hmenu, ui, TRUE, &mii))
  197. {
  198. Print("%2d: id=0x%04x ref=0x%p ", ui, mii.wID, mii.dwItemData);
  199. if (mii.fType & MFT_BITMAP)
  200. {
  201. Print("bitmap 0x%p ", mii.dwTypeData);
  202. }
  203. else if (mii.fType & MFT_OWNERDRAW)
  204. {
  205. Print("ownerdraw 0x%p ", mii.dwTypeData);
  206. }
  207. else if (mii.fType & MFT_SEPARATOR)
  208. {
  209. Print("separator ");
  210. }
  211. else
  212. {
  213. Print("string \"%s\" ", mii.dwTypeData);
  214. }
  215. if (mii.fType & MFT_MENUBARBREAK)
  216. Print("MFT_MENUBARBREAK ");
  217. if (mii.fType & MFT_MENUBREAK)
  218. Print("MFT_MENUBREAK ");
  219. if (mii.fType & MFT_RADIOCHECK)
  220. Print("MFT_RADIOCHECK ");
  221. if (mii.fType & MFT_RIGHTJUSTIFY)
  222. Print("MFT_RIGHTJUSTIFY ");
  223. if (mii.fType & MFT_RIGHTORDER)
  224. Print("MFT_RIGHTORDER ");
  225. if (mii.fState & MFS_CHECKED)
  226. Print("MFS_CHECKED ");
  227. if (mii.fState & MFS_DEFAULT)
  228. Print("MFS_DEFAULT ");
  229. if (mii.fState & MFS_DISABLED)
  230. Print("MFS_DISABLED ");
  231. if (mii.fState & MFS_GRAYED)
  232. Print("MFS_GRAYED ");
  233. if (mii.fState & MFS_HILITE)
  234. Print("MFS_HILITE ");
  235. if (mii.hSubMenu)
  236. Print("-> 0x%p ", mii.hSubMenu);
  237. Print("\n");
  238. }
  239. }
  240. return TRUE;
  241. }
  242. /***********************************************************************/
  243. #include <pshpack1.h>
  244. #define CC_BUTTON 0x80 /* Class codes */
  245. #define CC_EDIT 0x81
  246. #define CC_STATIC 0x82
  247. #define CC_LISTBOX 0x83
  248. #define CC_SCROLLBAR 0x84
  249. #define CC_COMBOBOX 0x85
  250. #define DS_DIALOGEX 0xFFFF0001
  251. typedef struct DIALOGDIMEN {
  252. WORD x;
  253. WORD y;
  254. WORD cx;
  255. WORD cy;
  256. } DIALOGDIMEN, *PDIALOGDIMEN;
  257. typedef struct DLGFINISH { /* Common dialog finish-up */
  258. WORD cDlgItems;
  259. DIALOGDIMEN dd;
  260. } DLGFINISH, *PDLGFINISH;
  261. typedef struct DLG {
  262. DWORD dwStyle; // or DS_DIALOGEX if DIALOGEX
  263. DWORD dwExStyle;
  264. DLGFINISH dlgfinish;
  265. WORD wszMenuName[1];
  266. /*
  267. * wszMenuName[] -- wsz or 0x00FF followed by WORD ordinal
  268. * wszClassName[] -- wsz or 0x00FF followed by WORD ordinal (?)
  269. * wszTitle[] -- wsz
  270. * if dwStyle & DS_SETFONT
  271. * WORD wPoint; // point size
  272. * wszFontName[] -- wsz
  273. * endif
  274. * followed by a packed array of DITs, each DWORD aligned
  275. */
  276. } DLG, *PDLG;
  277. typedef struct DLGEX {
  278. WORD wDlgVer; /* Version number; always 0001 */
  279. WORD wSignature; /* Always 0xFFFF */
  280. DWORD dwHelpID;
  281. DWORD dwExStyle;
  282. DWORD dwStyle;
  283. DLGFINISH dlgfinish;
  284. /*
  285. * wszMenuName[] -- wsz or 0x00FF followed by WORD ordinal
  286. * wszClassName[] -- wsz or 0x00FF followed by WORD ordinal (?)
  287. * wszTitle[] -- wsz
  288. * if dwStyle & DS_SETFONT
  289. * WORD wPoint; // point size
  290. * WORD wWeight;
  291. * BYTE bItalic;
  292. * BYTE bCharSet;
  293. * wszFontName[] -- wsz
  294. * endif
  295. * followed by a packed array of DITEX'es, each DWORD aligned
  296. */
  297. } DLGEX, *PDLGEX;
  298. typedef struct DIT { /* dialog item template */
  299. DWORD dwStyle;
  300. DWORD dwExStyle;
  301. DIALOGDIMEN dd;
  302. WORD wID;
  303. /*
  304. * wszClassName[] -- wsz or 0xFFFF followed by WORD ordinal
  305. * wszTitle[] -- wsz
  306. * cbExtra -- word value
  307. */
  308. } DIT, *PDIT;
  309. typedef struct DITEX {
  310. DWORD dwHelpID;
  311. DWORD dwExStyle;
  312. DWORD dwStyle;
  313. DIALOGDIMEN dd;
  314. DWORD dwID;
  315. /*
  316. * wszClassName[] -- wsz or 0xFFFF followed by WORD ordinal
  317. * wszTitle[] -- wsz
  318. * cbExtra -- word value
  319. */
  320. } DITEX, *PDITEX;
  321. #include <poppack.h>
  322. BOOL _MoveBlock(LPVOID pvDst, LPVOID pvSrc, DWORD cb)
  323. {
  324. BOOL fSuccess = tryMoveBlock(pvDst, pvSrc, cb);
  325. if (fSuccess) return fSuccess;
  326. Print("Error reading %d bytes from %p\n", cb, pvSrc);
  327. return FALSE;
  328. }
  329. LPCSTR DlgGetClassName(WORD wClass)
  330. {
  331. switch (wClass) { /* Handle internal class types */
  332. case CC_BUTTON: return "button";
  333. case CC_EDIT: return "edit";
  334. case CC_STATIC: return "static";
  335. case CC_LISTBOX: return "listbox";
  336. case CC_SCROLLBAR: return "scrollbar";
  337. case CC_COMBOBOX: return "combobox";
  338. default: return "<unknown>";
  339. }
  340. }
  341. typedef LPCSTR (*ORDINALRESOLVER)(WORD w);
  342. LPBYTE DlgDumpString(LPCSTR pszField, LPBYTE pArg, ORDINALRESOLVER Resolve)
  343. {
  344. WCHAR wch;
  345. Print("%s: ", pszField);
  346. if (!_MoveBlock(&wch, pArg, sizeof(wch))) return NULL;
  347. pArg += sizeof(wch);
  348. if (wch == 0xFF || wch == 0xFFFF)
  349. {
  350. if (!_MoveBlock(&wch, pArg, sizeof(wch))) return NULL;
  351. pArg += sizeof(wch);
  352. LPCSTR pszOrdinal;
  353. if (Resolve && (pszOrdinal = Resolve(wch)))
  354. {
  355. Print("%s\n", pszOrdinal);
  356. }
  357. else
  358. {
  359. Print("#0x%04x\n", wch);
  360. }
  361. return pArg;
  362. }
  363. Print("\"");
  364. while (wch) {
  365. Print("%c", wch); // truncate to ANSI, sorry
  366. if (IsCtrlCHit()) return NULL;
  367. if (!_MoveBlock(&wch, pArg, sizeof(wch))) return NULL;
  368. pArg += sizeof(wch);
  369. }
  370. Print("\"\n");
  371. return pArg;
  372. }
  373. LPBYTE DlgDwordAlign(LPBYTE pBase, LPBYTE pArg)
  374. {
  375. SIZE_T diff = pArg - pBase;
  376. if (diff % 4) pArg += 4 - (diff % 4);
  377. return pArg;
  378. }
  379. void DumpDialogEx(LPBYTE pArg)
  380. {
  381. DLGEX dlg;
  382. LPBYTE pBase = pArg;
  383. WORD w;
  384. if (!_MoveBlock(&dlg, pArg, sizeof(dlg))) return;
  385. Print(" wDlgVer = 0x%04x\n", dlg.wDlgVer);
  386. Print(" dwStyle = 0x%08x\n", dlg.dwStyle);
  387. Print("dwExStyle = 0x%08x\n", dlg.dwExStyle);
  388. Print(" dwHelpID = 0x%08x\n", dlg.dwHelpID);
  389. Print(" ( x, y) = (%3d, %3d)\n", dlg.dlgfinish.dd.x, dlg.dlgfinish.dd.y);
  390. Print(" (cx,cy) = (%3d, %3d)\n", dlg.dlgfinish.dd.cx, dlg.dlgfinish.dd.cy);
  391. pArg += FIELD_OFFSET(DLG, wszMenuName);
  392. pArg = DlgDumpString("Menu", pArg, NULL);
  393. if (!pArg) return;
  394. pArg = DlgDumpString("Class", pArg, NULL);
  395. if (!pArg) return;
  396. pArg = DlgDumpString("Title", pArg, NULL);
  397. if (!pArg) return;
  398. if (dlg.dwStyle & DS_SETFONT)
  399. {
  400. struct {
  401. WORD wPoint;
  402. WORD wWeight;
  403. BYTE bItalic;
  404. BYTE bCharSet;
  405. } ft;
  406. if (!_MoveBlock(&ft, pArg, sizeof(ft))) return;
  407. pArg += sizeof(ft);
  408. pArg = DlgDumpString("Font", pArg, NULL);
  409. if (!pArg) return;
  410. Print(" %dpt, weight=%d, italic=%d, charset=%d\n",
  411. ft.wPoint, ft.wWeight, ft.bItalic, ft.bCharSet);
  412. }
  413. // and then a packed array of DITEXs, DWORD-aligned
  414. Print("Number of controls: %d\n\n", dlg.dlgfinish.cDlgItems);
  415. for (int i = 0; !IsCtrlCHit() && i < dlg.dlgfinish.cDlgItems; i++)
  416. {
  417. pArg = DlgDwordAlign(pBase, pArg);
  418. DITEX dit;
  419. if (!_MoveBlock(&dit, pArg, sizeof(dit))) return;
  420. pArg += sizeof(dit);
  421. Print("Control %d (0x%04x):\n", dit.dwID, dit.dwID);
  422. Print(" dwStyle = 0x%08x\n", dit.dwStyle);
  423. Print(" dwExStyle = 0x%08x\n", dit.dwExStyle);
  424. Print(" dwHelpID = 0x%08x\n", dit.dwHelpID);
  425. Print(" ( x, y) = (%3d, %3d)\n", dit.dd.x, dit.dd.y);
  426. Print(" (cx,cy) = (%3d, %3d)\n", dit.dd.cx, dit.dd.cy);
  427. pArg = DlgDumpString(" Class", pArg, DlgGetClassName);
  428. if (!pArg) return;
  429. pArg = DlgDumpString(" Title", pArg, DlgGetClassName);
  430. if (!pArg) return;
  431. if (!_MoveBlock(&w, pArg, sizeof(w))) return;
  432. pArg += sizeof(w);
  433. pArg += w;
  434. }
  435. }
  436. void DumpDialog(LPBYTE pArg)
  437. {
  438. DLG dlg;
  439. LPBYTE pBase = pArg;
  440. WORD w;
  441. if (!_MoveBlock(&dlg, pArg, sizeof(dlg))) return;
  442. Print(" dwStyle = 0x%08x\n", dlg.dwStyle);
  443. Print("dwExStyle = 0x%08x\n", dlg.dwExStyle);
  444. Print(" ( x, y) = (%3d, %3d)\n", dlg.dlgfinish.dd.x, dlg.dlgfinish.dd.y);
  445. Print(" (cx,cy) = (%3d, %3d)\n", dlg.dlgfinish.dd.cx, dlg.dlgfinish.dd.cy);
  446. pArg += FIELD_OFFSET(DLG, wszMenuName);
  447. pArg = DlgDumpString("Menu", pArg, NULL);
  448. if (!pArg) return;
  449. pArg = DlgDumpString("Class", pArg, NULL);
  450. if (!pArg) return;
  451. pArg = DlgDumpString("Title", pArg, NULL);
  452. if (!pArg) return;
  453. if (dlg.dwStyle & DS_SETFONT)
  454. {
  455. if (!_MoveBlock(&w, pArg, sizeof(w))) return;
  456. pArg += sizeof(WORD);
  457. pArg = DlgDumpString("Font", pArg, NULL);
  458. if (!pArg) return;
  459. Print(" Font size: %dpt\n", w);
  460. }
  461. // and then a packed array of DITs, DWORD-aligned
  462. Print("Number of controls: %d\n\n", dlg.dlgfinish.cDlgItems);
  463. for (int i = 0; !IsCtrlCHit() && i < dlg.dlgfinish.cDlgItems; i++)
  464. {
  465. pArg = DlgDwordAlign(pBase, pArg);
  466. DIT dit;
  467. if (!_MoveBlock(&dit, pArg, sizeof(dit))) return;
  468. pArg += sizeof(dit);
  469. Print("Control %d (0x%04x):\n", (short)dit.wID, dit.wID);
  470. Print(" dwStyle = 0x%08x\n", dit.dwStyle);
  471. Print(" dwExStyle = 0x%08x\n", dit.dwExStyle);
  472. Print(" ( x, y) = (%3d, %3d)\n", dit.dd.x, dit.dd.y);
  473. Print(" (cx,cy) = (%3d, %3d)\n", dit.dd.cx, dit.dd.cy);
  474. pArg = DlgDumpString(" Class", pArg, DlgGetClassName);
  475. if (!pArg) return;
  476. pArg = DlgDumpString(" Title", pArg, DlgGetClassName);
  477. if (!pArg) return;
  478. if (!_MoveBlock(&w, pArg, sizeof(w))) return;
  479. pArg += sizeof(w);
  480. pArg += w;
  481. }
  482. }
  483. extern "C" BOOL Idlgt(DWORD dwOpts,
  484. LPVOID pArg )
  485. {
  486. int cItems;
  487. PDLGFINISH pdlgfinish;
  488. DWORD dw;
  489. if (!_MoveBlock(&dw, pArg, sizeof(dw)))
  490. {
  491. return TRUE;
  492. }
  493. if (dw == DS_DIALOGEX)
  494. {
  495. DumpDialogEx((LPBYTE)pArg);
  496. }
  497. else
  498. {
  499. DumpDialog((LPBYTE)pArg);
  500. }
  501. return TRUE;
  502. }