details.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. /*
  2. * OleView (details.c)
  3. *
  4. * Copyright 2006 Piotr Caban
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  19. */
  20. #include "main.h"
  21. DETAILS details;
  22. static const WCHAR wszAppID[] = { 'A','p','p','I','D','\0' };
  23. static const WCHAR wszCLSID[] = { 'C','L','S','I','D','\0' };
  24. static const WCHAR wszProgID[] = { 'P','r','o','g','I','D','\0' };
  25. static const WCHAR wszProxyStubClsid32[] =
  26. { 'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2','\0' };
  27. static const WCHAR wszTypeLib[] = { 'T','y','p','e','L','i','b','\0' };
  28. static void CreateRegRec(HKEY hKey, HTREEITEM parent, WCHAR *wszKeyName, BOOL addings)
  29. {
  30. int i=0, j, retEnum;
  31. HKEY hCurKey;
  32. DWORD lenName, lenData, valType;
  33. WCHAR wszName[MAX_LOAD_STRING];
  34. WCHAR wszData[MAX_LOAD_STRING];
  35. WCHAR wszTree[MAX_LOAD_STRING];
  36. const WCHAR wszBinary[] = { '%','0','2','X',' ','\0' };
  37. const WCHAR wszDots[] = { '.','.','.','\0' };
  38. const WCHAR wszFormat1[] = { '%','s',' ','[','%','s',']',' ','=',' ','%','s','\0' };
  39. const WCHAR wszFormat2[] = { '%','s',' ','=',' ','%','s','\0' };
  40. TVINSERTSTRUCTW tvis;
  41. HTREEITEM addPlace = parent;
  42. U(tvis).item.mask = TVIF_TEXT;
  43. U(tvis).item.cchTextMax = MAX_LOAD_STRING;
  44. U(tvis).item.pszText = wszTree;
  45. tvis.hInsertAfter = TVI_LAST;
  46. tvis.hParent = parent;
  47. while(TRUE)
  48. {
  49. lenName = ARRAY_SIZE(wszName);
  50. lenData = sizeof(wszData);
  51. retEnum = RegEnumValueW(hKey, i, wszName, &lenName,
  52. NULL, &valType, (LPBYTE)wszData, &lenData);
  53. if(retEnum != ERROR_SUCCESS)
  54. {
  55. if(!i && lstrlenW(wszKeyName) > 1)
  56. {
  57. U(tvis).item.pszText = wszKeyName;
  58. addPlace = TreeView_InsertItemW(details.hReg, &tvis);
  59. U(tvis).item.pszText = wszTree;
  60. }
  61. break;
  62. }
  63. if(valType == REG_BINARY)
  64. {
  65. WCHAR wszBuf[MAX_LOAD_STRING];
  66. for(j=0; j<MAX_LOAD_STRING/3-1; j++)
  67. wsprintfW(&wszBuf[3*j], wszBinary, (int)((unsigned char)wszData[j]));
  68. wszBuf[(lenData*3>=MAX_LOAD_STRING ? MAX_LOAD_STRING-1 : lenData*3)] = '\0';
  69. lstrcpyW(wszData, wszBuf);
  70. lstrcpyW(&wszData[MAX_LOAD_STRING-5], wszDots);
  71. }
  72. if(lenName) wsprintfW(wszTree, wszFormat1, wszKeyName, wszName, wszData);
  73. else wsprintfW(wszTree, wszFormat2, wszKeyName, wszData);
  74. addPlace = TreeView_InsertItemW(details.hReg, &tvis);
  75. if(addings && !memcmp(wszName, wszAppID, sizeof(WCHAR[6])))
  76. {
  77. lstrcpyW(wszTree, wszName);
  78. memmove(&wszData[6], wszData, sizeof(WCHAR[MAX_LOAD_STRING-6]));
  79. lstrcpyW(wszData, wszCLSID);
  80. wszData[5] = '\\';
  81. if(RegOpenKeyW(HKEY_CLASSES_ROOT, wszData, &hCurKey) != ERROR_SUCCESS)
  82. {
  83. i++;
  84. continue;
  85. }
  86. tvis.hParent = TVI_ROOT;
  87. tvis.hParent = TreeView_InsertItemW(details.hReg, &tvis);
  88. lenName = sizeof(wszName);
  89. RegQueryValueW(hCurKey, NULL, wszName, (LONG *)&lenName);
  90. RegCloseKey(hCurKey);
  91. wsprintfW(wszTree, wszFormat2, &wszData[6], wszName);
  92. SendMessageW(details.hReg, TVM_INSERTITEMW, 0, (LPARAM)&tvis);
  93. SendMessageW(details.hReg, TVM_EXPAND, TVE_EXPAND, (LPARAM)tvis.hParent);
  94. tvis.hParent = parent;
  95. }
  96. i++;
  97. }
  98. i=-1;
  99. while(TRUE)
  100. {
  101. i++;
  102. if(RegEnumKeyW(hKey, i, wszName, ARRAY_SIZE(wszName)) != ERROR_SUCCESS) break;
  103. if(RegOpenKeyW(hKey, wszName, &hCurKey) != ERROR_SUCCESS) continue;
  104. CreateRegRec(hCurKey, addPlace, wszName, addings);
  105. SendMessageW(details.hReg, TVM_EXPAND, TVE_EXPAND, (LPARAM)addPlace);
  106. if(addings && !memcmp(wszName, wszProgID, sizeof(WCHAR[7])))
  107. {
  108. lenData = sizeof(wszData);
  109. RegQueryValueW(hCurKey, NULL, wszData, (LONG *)&lenData);
  110. RegCloseKey(hCurKey);
  111. if(RegOpenKeyW(HKEY_CLASSES_ROOT, wszData, &hCurKey) != ERROR_SUCCESS)
  112. continue;
  113. CreateRegRec(hCurKey, TVI_ROOT, wszData, FALSE);
  114. }
  115. else if(addings && !memcmp(wszName, wszProxyStubClsid32, sizeof(WCHAR[17])))
  116. {
  117. lenData = sizeof(wszData);
  118. RegQueryValueW(hCurKey, NULL, wszData, (LONG *)&lenData);
  119. RegCloseKey(hCurKey);
  120. RegOpenKeyW(HKEY_CLASSES_ROOT, wszCLSID, &hCurKey);
  121. lenName = sizeof(wszName);
  122. RegQueryValueW(hCurKey, NULL, wszName, (LONG *)&lenName);
  123. tvis.hParent = TVI_ROOT;
  124. wsprintfW(wszTree, wszFormat2, wszCLSID, wszName);
  125. tvis.hParent = TreeView_InsertItemW(details.hReg, &tvis);
  126. RegCloseKey(hCurKey);
  127. memmove(&wszData[6], wszData, lenData);
  128. memcpy(wszData, wszCLSID, sizeof(WCHAR[6]));
  129. wszData[5] = '\\';
  130. RegOpenKeyW(HKEY_CLASSES_ROOT, wszData, &hCurKey);
  131. CreateRegRec(hCurKey, tvis.hParent, &wszData[6], FALSE);
  132. SendMessageW(details.hReg, TVM_EXPAND, TVE_EXPAND, (LPARAM)tvis.hParent);
  133. tvis.hParent = parent;
  134. }
  135. else if(addings && !memcmp(wszName, wszTypeLib, sizeof(WCHAR[8])))
  136. {
  137. lenData = sizeof(wszData);
  138. RegQueryValueW(hCurKey, NULL, wszData, (LONG *)&lenData);
  139. RegCloseKey(hCurKey);
  140. RegOpenKeyW(HKEY_CLASSES_ROOT, wszTypeLib, &hCurKey);
  141. lenName = sizeof(wszName);
  142. RegQueryValueW(hCurKey, NULL, wszName, (LONG *)&lenName);
  143. tvis.hParent = TVI_ROOT;
  144. wsprintfW(wszTree, wszFormat2, wszTypeLib, wszName);
  145. tvis.hParent = TreeView_InsertItemW(details.hReg, &tvis);
  146. RegCloseKey(hCurKey);
  147. memmove(&wszData[8], wszData, lenData);
  148. memcpy(wszData, wszTypeLib, sizeof(WCHAR[8]));
  149. wszData[7] = '\\';
  150. RegOpenKeyW(HKEY_CLASSES_ROOT, wszData, &hCurKey);
  151. CreateRegRec(hCurKey, tvis.hParent, &wszData[8], FALSE);
  152. SendMessageW(details.hReg, TVM_EXPAND, TVE_EXPAND, (LPARAM)tvis.hParent);
  153. tvis.hParent = parent;
  154. }
  155. RegCloseKey(hCurKey);
  156. }
  157. }
  158. static void CreateReg(WCHAR *buffer)
  159. {
  160. HKEY hKey;
  161. DWORD lenBuffer=-1, lastLenBuffer, lenTree;
  162. WCHAR *path;
  163. WCHAR wszTree[MAX_LOAD_STRING];
  164. TVINSERTSTRUCTW tvis;
  165. HTREEITEM addPlace = TVI_ROOT;
  166. U(tvis).item.mask = TVIF_TEXT;
  167. U(tvis).item.cchTextMax = MAX_LOAD_STRING;
  168. U(tvis).item.pszText = wszTree;
  169. tvis.hInsertAfter = TVI_LAST;
  170. tvis.hParent = TVI_ROOT;
  171. path = buffer;
  172. while(TRUE)
  173. {
  174. while(*path != '\\' && *path != '\0') path += 1;
  175. if(*path == '\\')
  176. {
  177. *path = '\0';
  178. if(RegOpenKeyW(HKEY_CLASSES_ROOT, buffer, &hKey) != ERROR_SUCCESS)
  179. return;
  180. lastLenBuffer = lenBuffer+1;
  181. lenBuffer = lstrlenW(buffer);
  182. *path = '\\';
  183. path += 1;
  184. lenTree = sizeof(wszTree);
  185. if(RegQueryValueW(hKey, NULL, wszTree, (LONG *)&lenTree) == ERROR_SUCCESS)
  186. {
  187. memmove(&wszTree[lenBuffer-lastLenBuffer+3], wszTree, lenTree);
  188. memcpy(wszTree, &buffer[lastLenBuffer],
  189. (lenBuffer - lastLenBuffer) * sizeof(WCHAR));
  190. if(lenTree == 1) wszTree[lenBuffer-lastLenBuffer] = '\0';
  191. else
  192. {
  193. wszTree[lenBuffer-lastLenBuffer] = ' ';
  194. wszTree[lenBuffer-lastLenBuffer+1] = '=';
  195. wszTree[lenBuffer-lastLenBuffer+2] = ' ';
  196. }
  197. addPlace = TreeView_InsertItemW(details.hReg, &tvis);
  198. }
  199. tvis.hParent = addPlace;
  200. RegCloseKey(hKey);
  201. }
  202. else break;
  203. }
  204. if(RegOpenKeyW(HKEY_CLASSES_ROOT, buffer, &hKey) != ERROR_SUCCESS) return;
  205. CreateRegRec(hKey, addPlace, &buffer[lenBuffer+1], TRUE);
  206. RegCloseKey(hKey);
  207. SendMessageW(details.hReg, TVM_EXPAND, TVE_EXPAND, (LPARAM)addPlace);
  208. SendMessageW(details.hReg, TVM_ENSUREVISIBLE, 0, (LPARAM)addPlace);
  209. }
  210. void RefreshDetails(HTREEITEM item)
  211. {
  212. TVITEMW tvi;
  213. WCHAR wszBuf[MAX_LOAD_STRING];
  214. WCHAR wszStaticText[MAX_LOAD_STRING];
  215. const WCHAR wszFormat[] = { '%','s','\n','%','s','\0' };
  216. BOOL show;
  217. memset(&tvi, 0, sizeof(TVITEMW));
  218. memset(&wszStaticText, 0, sizeof(WCHAR[MAX_LOAD_STRING]));
  219. tvi.mask = TVIF_TEXT;
  220. tvi.hItem = item;
  221. tvi.pszText = wszBuf;
  222. tvi.cchTextMax = MAX_LOAD_STRING;
  223. SendMessageW(globals.hTree, TVM_GETITEMW, 0, (LPARAM)&tvi);
  224. if(tvi.lParam)
  225. wsprintfW(wszStaticText, wszFormat, tvi.pszText, ((ITEM_INFO *)tvi.lParam)->clsid);
  226. else lstrcpyW(wszStaticText, tvi.pszText);
  227. SetWindowTextW(details.hStatic, wszStaticText);
  228. SendMessageW(details.hTab, TCM_SETCURSEL, 0, 0);
  229. if(tvi.lParam && ((ITEM_INFO *)tvi.lParam)->cFlag & SHOWALL)
  230. {
  231. if(SendMessageW(details.hTab, TCM_GETITEMCOUNT, 0, 0) == 1)
  232. {
  233. TCITEMW tci;
  234. memset(&tci, 0, sizeof(TCITEMW));
  235. tci.mask = TCIF_TEXT;
  236. tci.pszText = wszBuf;
  237. tci.cchTextMax = ARRAY_SIZE(wszBuf);
  238. LoadStringW(globals.hMainInst, IDS_TAB_IMPL, wszBuf, ARRAY_SIZE(wszBuf));
  239. SendMessageW(details.hTab, TCM_INSERTITEMW, 1, (LPARAM)&tci);
  240. LoadStringW(globals.hMainInst, IDS_TAB_ACTIV, wszBuf, ARRAY_SIZE(wszBuf));
  241. SendMessageW(details.hTab, TCM_INSERTITEMW, 2, (LPARAM)&tci);
  242. }
  243. }
  244. else
  245. {
  246. SendMessageW(details.hTab, TCM_DELETEITEM, 2, 0);
  247. SendMessageW(details.hTab, TCM_DELETEITEM, 1, 0);
  248. }
  249. show = CreateRegPath(item, wszBuf, MAX_LOAD_STRING);
  250. ShowWindow(details.hTab, show ? SW_SHOW : SW_HIDE);
  251. /* FIXME Next line deals with TreeView_EnsureVisible bug */
  252. SendMessageW(details.hReg, TVM_ENSUREVISIBLE, 0,
  253. SendMessageW(details.hReg, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)TVI_ROOT));
  254. SendMessageW(details.hReg, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT);
  255. if(show) CreateReg(wszBuf);
  256. }
  257. static void CreateTabCtrl(HWND hWnd)
  258. {
  259. TCITEMW tci;
  260. WCHAR buffer[MAX_LOAD_STRING];
  261. memset(&tci, 0, sizeof(TCITEMW));
  262. tci.mask = TCIF_TEXT;
  263. tci.pszText = buffer;
  264. tci.cchTextMax = ARRAY_SIZE(buffer);
  265. details.hTab = CreateWindowW(WC_TABCONTROLW, NULL, WS_CHILD|WS_VISIBLE,
  266. 0, 0, 0, 0, hWnd, (HMENU)TAB_WINDOW, globals.hMainInst, NULL);
  267. ShowWindow(details.hTab, SW_HIDE);
  268. LoadStringW(globals.hMainInst, IDS_TAB_REG, buffer, ARRAY_SIZE(buffer));
  269. SendMessageW(details.hTab, TCM_INSERTITEMW, 0, (LPARAM)&tci);
  270. details.hReg = CreateWindowExW(WS_EX_CLIENTEDGE, WC_TREEVIEWW, NULL,
  271. WS_CHILD|WS_VISIBLE|TVS_HASLINES,
  272. 0, 0, 0, 0, details.hTab, NULL, globals.hMainInst, NULL);
  273. }
  274. static LRESULT CALLBACK DetailsProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  275. {
  276. int sel;
  277. switch(uMsg)
  278. {
  279. case WM_CREATE:
  280. {
  281. const WCHAR wszStatic[] = { 'S','t','a','t','i','c','\0' };
  282. details.hStatic = CreateWindowW(wszStatic, NULL, WS_CHILD|WS_VISIBLE,
  283. 0, 0, 0, 0, hWnd, NULL, globals.hMainInst, NULL);
  284. CreateTabCtrl(hWnd);
  285. }
  286. break;
  287. case WM_SIZE:
  288. MoveWindow(details.hStatic, 0, 0, LOWORD(lParam), 40, TRUE);
  289. MoveWindow(details.hTab, 3, 40, LOWORD(lParam)-6, HIWORD(lParam)-43, TRUE);
  290. MoveWindow(details.hReg, 10, 34, LOWORD(lParam)-26,
  291. HIWORD(lParam)-87, TRUE);
  292. break;
  293. case WM_NOTIFY:
  294. if((int)wParam != TAB_WINDOW) break;
  295. switch(((LPNMHDR)lParam)->code)
  296. {
  297. case TCN_SELCHANGE:
  298. ShowWindow(details.hReg, SW_HIDE);
  299. sel = SendMessageW(details.hTab, TCM_GETCURSEL, 0, 0);
  300. if(sel==0) ShowWindow(details.hReg, SW_SHOW);
  301. break;
  302. }
  303. break;
  304. default:
  305. return DefWindowProcW(hWnd, uMsg, wParam, lParam);
  306. }
  307. return 0;
  308. }
  309. HWND CreateDetailsWindow(HINSTANCE hInst)
  310. {
  311. WNDCLASSW wcd;
  312. const WCHAR wszDetailsClass[] = { 'D','E','T','A','I','L','S','\0' };
  313. memset(&wcd, 0, sizeof(WNDCLASSW));
  314. wcd.lpfnWndProc = DetailsProc;
  315. wcd.lpszClassName = wszDetailsClass;
  316. wcd.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  317. wcd.hCursor = LoadCursorW(0, (LPCWSTR)IDC_ARROW);
  318. if(!RegisterClassW(&wcd)) return NULL;
  319. globals.hDetails = CreateWindowExW(WS_EX_CLIENTEDGE, wszDetailsClass, NULL,
  320. WS_CHILD|WS_VISIBLE, 0, 0, 0, 0, globals.hPaneWnd, NULL, hInst, NULL);
  321. return globals.hDetails;
  322. }