d3d8/tests: Add a system memory miptree layout test.
[wine.git] / programs / oleview / details.c
blobb194f6f699a1b010b7508af3e13a7833be5d6ca8
1 /*
2 * OleView (details.c)
4 * Copyright 2006 Piotr Caban
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.
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.
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
21 #include "main.h"
23 DETAILS details;
24 static const WCHAR wszAppID[] = { 'A','p','p','I','D','\0' };
25 static const WCHAR wszCLSID[] = { 'C','L','S','I','D','\0' };
26 static const WCHAR wszProgID[] = { 'P','r','o','g','I','D','\0' };
27 static const WCHAR wszProxyStubClsid32[] =
28 { 'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2','\0' };
29 static const WCHAR wszTypeLib[] = { 'T','y','p','e','L','i','b','\0' };
31 static void CreateRegRec(HKEY hKey, HTREEITEM parent, WCHAR *wszKeyName, BOOL addings)
33 int i=0, j, retEnum;
34 HKEY hCurKey;
35 DWORD lenName, lenData, valType;
36 WCHAR wszName[MAX_LOAD_STRING];
37 WCHAR wszData[MAX_LOAD_STRING];
38 WCHAR wszTree[MAX_LOAD_STRING];
39 const WCHAR wszBinary[] = { '%','0','2','X',' ','\0' };
40 const WCHAR wszDots[] = { '.','.','.','\0' };
41 const WCHAR wszFormat1[] = { '%','s',' ','[','%','s',']',' ','=',' ','%','s','\0' };
42 const WCHAR wszFormat2[] = { '%','s',' ','=',' ','%','s','\0' };
43 TVINSERTSTRUCTW tvis;
44 HTREEITEM addPlace = parent;
46 U(tvis).item.mask = TVIF_TEXT;
47 U(tvis).item.cchTextMax = MAX_LOAD_STRING;
48 U(tvis).item.pszText = wszTree;
49 tvis.hInsertAfter = TVI_LAST;
50 tvis.hParent = parent;
52 while(TRUE)
54 lenName = sizeof(wszName)/sizeof(WCHAR);
55 lenData = sizeof(wszData);
57 retEnum = RegEnumValueW(hKey, i, wszName, &lenName,
58 NULL, &valType, (LPBYTE)wszData, &lenData);
60 if(retEnum != ERROR_SUCCESS)
62 if(!i && lstrlenW(wszKeyName) > 1)
64 U(tvis).item.pszText = wszKeyName;
65 addPlace = TreeView_InsertItemW(details.hReg, &tvis);
66 U(tvis).item.pszText = wszTree;
68 break;
71 if(valType == REG_BINARY)
73 WCHAR wszBuf[MAX_LOAD_STRING];
75 for(j=0; j<MAX_LOAD_STRING/3-1; j++)
76 wsprintfW(&wszBuf[3*j], wszBinary, (int)((unsigned char)wszData[j]));
77 wszBuf[(lenData*3>=MAX_LOAD_STRING ? MAX_LOAD_STRING-1 : lenData*3)] = '\0';
78 lstrcpyW(wszData, wszBuf);
79 lstrcpyW(&wszData[MAX_LOAD_STRING-5], wszDots);
82 if(lenName) wsprintfW(wszTree, wszFormat1, wszKeyName, wszName, wszData);
83 else wsprintfW(wszTree, wszFormat2, wszKeyName, wszData);
85 addPlace = TreeView_InsertItemW(details.hReg, &tvis);
87 if(addings && !memcmp(wszName, wszAppID, sizeof(WCHAR[6])))
89 lstrcpyW(wszTree, wszName);
90 memmove(&wszData[6], wszData, sizeof(WCHAR[MAX_LOAD_STRING-6]));
91 lstrcpyW(wszData, wszCLSID);
92 wszData[5] = '\\';
94 if(RegOpenKeyW(HKEY_CLASSES_ROOT, wszData, &hCurKey) != ERROR_SUCCESS)
96 i++;
97 continue;
100 tvis.hParent = TVI_ROOT;
101 tvis.hParent = TreeView_InsertItemW(details.hReg, &tvis);
103 lenName = sizeof(wszName);
104 RegQueryValueW(hCurKey, NULL, wszName, (LONG *)&lenName);
105 RegCloseKey(hCurKey);
107 wsprintfW(wszTree, wszFormat2, &wszData[6], wszName);
109 SendMessageW(details.hReg, TVM_INSERTITEMW, 0, (LPARAM)&tvis);
110 SendMessageW(details.hReg, TVM_EXPAND, TVE_EXPAND, (LPARAM)tvis.hParent);
112 tvis.hParent = parent;
114 i++;
117 i=-1;
119 while(TRUE)
121 i++;
123 if(RegEnumKeyW(hKey, i, wszName, sizeof(wszName)/sizeof(WCHAR)) != ERROR_SUCCESS) break;
125 if(RegOpenKeyW(hKey, wszName, &hCurKey) != ERROR_SUCCESS) continue;
127 CreateRegRec(hCurKey, addPlace, wszName, addings);
128 SendMessageW(details.hReg, TVM_EXPAND, TVE_EXPAND, (LPARAM)addPlace);
130 if(addings && !memcmp(wszName, wszProgID, sizeof(WCHAR[7])))
132 lenData = sizeof(wszData);
133 RegQueryValueW(hCurKey, NULL, wszData, (LONG *)&lenData);
134 RegCloseKey(hCurKey);
136 if(RegOpenKeyW(HKEY_CLASSES_ROOT, wszData, &hCurKey) != ERROR_SUCCESS)
137 continue;
138 CreateRegRec(hCurKey, TVI_ROOT, wszData, FALSE);
140 else if(addings && !memcmp(wszName, wszProxyStubClsid32, sizeof(WCHAR[17])))
142 lenData = sizeof(WCHAR[MAX_LOAD_STRING]);
144 RegQueryValueW(hCurKey, NULL, wszData, (LONG *)&lenData);
145 RegCloseKey(hCurKey);
147 RegOpenKeyW(HKEY_CLASSES_ROOT, wszCLSID, &hCurKey);
149 lenName = sizeof(wszName);
150 RegQueryValueW(hCurKey, NULL, wszName, (LONG *)&lenName);
152 tvis.hParent = TVI_ROOT;
153 wsprintfW(wszTree, wszFormat2, wszCLSID, wszName);
154 tvis.hParent = TreeView_InsertItemW(details.hReg, &tvis);
156 RegCloseKey(hCurKey);
158 memmove(&wszData[6], wszData, lenData * sizeof(WCHAR));
159 memcpy(wszData, wszCLSID, sizeof(WCHAR[6]));
160 wszData[5] = '\\';
162 RegOpenKeyW(HKEY_CLASSES_ROOT, wszData, &hCurKey);
164 CreateRegRec(hCurKey, tvis.hParent, &wszData[6], FALSE);
166 SendMessageW(details.hReg, TVM_EXPAND, TVE_EXPAND, (LPARAM)tvis.hParent);
167 tvis.hParent = parent;
169 else if(addings && !memcmp(wszName, wszTypeLib, sizeof(WCHAR[8])))
171 lenData = sizeof(wszData);
172 RegQueryValueW(hCurKey, NULL, wszData, (LONG *)&lenData);
173 RegCloseKey(hCurKey);
175 RegOpenKeyW(HKEY_CLASSES_ROOT, wszTypeLib, &hCurKey);
177 lenName = sizeof(wszName);
178 RegQueryValueW(hCurKey, NULL, wszName, (LONG *)&lenName);
180 tvis.hParent = TVI_ROOT;
181 wsprintfW(wszTree, wszFormat2, wszTypeLib, wszName);
182 tvis.hParent = TreeView_InsertItemW(details.hReg, &tvis);
184 RegCloseKey(hCurKey);
186 memmove(&wszData[8], wszData, lenData * sizeof(WCHAR));
187 memcpy(wszData, wszTypeLib, sizeof(WCHAR[8]));
188 wszData[7] = '\\';
189 RegOpenKeyW(HKEY_CLASSES_ROOT, wszData, &hCurKey);
191 CreateRegRec(hCurKey, tvis.hParent, &wszData[8], FALSE);
193 SendMessageW(details.hReg, TVM_EXPAND, TVE_EXPAND, (LPARAM)tvis.hParent);
194 tvis.hParent = parent;
196 RegCloseKey(hCurKey);
200 static void CreateReg(WCHAR *buffer)
202 HKEY hKey;
203 DWORD lenBuffer=-1, lastLenBuffer, lenTree;
204 WCHAR *path;
205 WCHAR wszTree[MAX_LOAD_STRING];
206 TVINSERTSTRUCTW tvis;
207 HTREEITEM addPlace = TVI_ROOT;
209 U(tvis).item.mask = TVIF_TEXT;
210 U(tvis).item.cchTextMax = MAX_LOAD_STRING;
211 U(tvis).item.pszText = wszTree;
212 tvis.hInsertAfter = TVI_LAST;
213 tvis.hParent = TVI_ROOT;
215 path = buffer;
216 while(TRUE)
218 while(*path != '\\' && *path != '\0') path += 1;
220 if(*path == '\\')
222 *path = '\0';
224 if(RegOpenKeyW(HKEY_CLASSES_ROOT, buffer, &hKey) != ERROR_SUCCESS)
225 return;
227 lastLenBuffer = lenBuffer+1;
228 lenBuffer = lstrlenW(buffer);
229 *path = '\\';
230 path += 1;
232 lenTree = sizeof(WCHAR[MAX_LOAD_STRING]);
234 if(RegQueryValueW(hKey, NULL, wszTree, (LONG *)&lenTree) == ERROR_SUCCESS)
236 memmove(&wszTree[lenBuffer-lastLenBuffer+3], wszTree,
237 lenTree * sizeof(WCHAR));
238 memcpy(wszTree, &buffer[lastLenBuffer],
239 (lenBuffer - lastLenBuffer) * sizeof(WCHAR));
241 if(lenTree == 1) wszTree[lenBuffer-lastLenBuffer] = '\0';
242 else
244 wszTree[lenBuffer-lastLenBuffer] = ' ';
245 wszTree[lenBuffer-lastLenBuffer+1] = '=';
246 wszTree[lenBuffer-lastLenBuffer+2] = ' ';
249 addPlace = TreeView_InsertItemW(details.hReg, &tvis);
252 tvis.hParent = addPlace;
253 RegCloseKey(hKey);
255 else break;
258 if(RegOpenKeyW(HKEY_CLASSES_ROOT, buffer, &hKey) != ERROR_SUCCESS) return;
260 CreateRegRec(hKey, addPlace, &buffer[lenBuffer+1], TRUE);
262 RegCloseKey(hKey);
264 SendMessageW(details.hReg, TVM_EXPAND, TVE_EXPAND, (LPARAM)addPlace);
265 SendMessageW(details.hReg, TVM_ENSUREVISIBLE, 0, (LPARAM)addPlace);
268 void RefreshDetails(HTREEITEM item)
270 TVITEMW tvi;
271 WCHAR wszBuf[MAX_LOAD_STRING];
272 WCHAR wszStaticText[MAX_LOAD_STRING];
273 const WCHAR wszFormat[] = { '%','s','\n','%','s','\0' };
274 BOOL show;
276 memset(&tvi, 0, sizeof(TVITEMW));
277 memset(&wszStaticText, 0, sizeof(WCHAR[MAX_LOAD_STRING]));
278 tvi.mask = TVIF_TEXT;
279 tvi.hItem = item;
280 tvi.pszText = wszBuf;
281 tvi.cchTextMax = MAX_LOAD_STRING;
282 SendMessageW(globals.hTree, TVM_GETITEMW, 0, (LPARAM)&tvi);
284 if(tvi.lParam)
285 wsprintfW(wszStaticText, wszFormat, tvi.pszText, ((ITEM_INFO *)tvi.lParam)->clsid);
286 else lstrcpyW(wszStaticText, tvi.pszText);
288 SetWindowTextW(details.hStatic, wszStaticText);
290 SendMessageW(details.hTab, TCM_SETCURSEL, 0, 0);
292 if(tvi.lParam && ((ITEM_INFO *)tvi.lParam)->cFlag & SHOWALL)
294 if(SendMessageW(details.hTab, TCM_GETITEMCOUNT, 0, 0) == 1)
296 TCITEMW tci;
297 memset(&tci, 0, sizeof(TCITEMW));
298 tci.mask = TCIF_TEXT;
299 tci.pszText = wszBuf;
300 tci.cchTextMax = sizeof(wszBuf)/sizeof(wszBuf[0]);
302 LoadStringW(globals.hMainInst, IDS_TAB_IMPL,
303 wszBuf, sizeof(wszBuf)/sizeof(wszBuf[0]));
304 SendMessageW(details.hTab, TCM_INSERTITEMW, 1, (LPARAM)&tci);
306 LoadStringW(globals.hMainInst, IDS_TAB_ACTIV,
307 wszBuf, sizeof(wszBuf)/sizeof(wszBuf[0]));
308 SendMessageW(details.hTab, TCM_INSERTITEMW, 2, (LPARAM)&tci);
311 else
313 SendMessageW(details.hTab, TCM_DELETEITEM, 2, 0);
314 SendMessageW(details.hTab, TCM_DELETEITEM, 1, 0);
317 show = CreateRegPath(item, wszBuf, MAX_LOAD_STRING);
318 ShowWindow(details.hTab, show ? SW_SHOW : SW_HIDE);
320 /* FIXME Next line deals with TreeView_EnsureVisible bug */
321 SendMessageW(details.hReg, TVM_ENSUREVISIBLE, 0,
322 SendMessageW(details.hReg, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)TVI_ROOT));
323 SendMessageW(details.hReg, TVM_DELETEITEM, 0, (LPARAM)TVI_ROOT);
324 if(show) CreateReg(wszBuf);
327 static void CreateTabCtrl(HWND hWnd)
329 TCITEMW tci;
330 WCHAR buffer[MAX_LOAD_STRING];
332 memset(&tci, 0, sizeof(TCITEMW));
333 tci.mask = TCIF_TEXT;
334 tci.pszText = buffer;
335 tci.cchTextMax = sizeof(buffer)/sizeof(buffer[0]);
337 details.hTab = CreateWindowW(WC_TABCONTROLW, NULL, WS_CHILD|WS_VISIBLE,
338 0, 0, 0, 0, hWnd, (HMENU)TAB_WINDOW, globals.hMainInst, NULL);
339 ShowWindow(details.hTab, SW_HIDE);
341 LoadStringW(globals.hMainInst, IDS_TAB_REG, buffer, sizeof(buffer)/sizeof(buffer[0]));
342 SendMessageW(details.hTab, TCM_INSERTITEMW, 0, (LPARAM)&tci);
344 details.hReg = CreateWindowExW(WS_EX_CLIENTEDGE, WC_TREEVIEWW, NULL,
345 WS_CHILD|WS_VISIBLE|TVS_HASLINES,
346 0, 0, 0, 0, details.hTab, NULL, globals.hMainInst, NULL);
349 static LRESULT CALLBACK DetailsProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
351 int sel;
353 switch(uMsg)
355 case WM_CREATE:
357 const WCHAR wszStatic[] = { 'S','t','a','t','i','c','\0' };
359 details.hStatic = CreateWindowW(wszStatic, NULL, WS_CHILD|WS_VISIBLE,
360 0, 0, 0, 0, hWnd, NULL, globals.hMainInst, NULL);
361 CreateTabCtrl(hWnd);
363 break;
364 case WM_SIZE:
365 MoveWindow(details.hStatic, 0, 0, LOWORD(lParam), 40, TRUE);
366 MoveWindow(details.hTab, 3, 40, LOWORD(lParam)-6, HIWORD(lParam)-43, TRUE);
367 MoveWindow(details.hReg, 10, 34, LOWORD(lParam)-26,
368 HIWORD(lParam)-87, TRUE);
369 break;
370 case WM_NOTIFY:
371 if((int)wParam != TAB_WINDOW) break;
372 switch(((LPNMHDR)lParam)->code)
374 case TCN_SELCHANGE:
375 ShowWindow(details.hReg, SW_HIDE);
376 sel = SendMessageW(details.hTab, TCM_GETCURSEL, 0, 0);
378 if(sel==0) ShowWindow(details.hReg, SW_SHOW);
379 break;
381 break;
382 default:
383 return DefWindowProcW(hWnd, uMsg, wParam, lParam);
385 return 0;
388 HWND CreateDetailsWindow(HINSTANCE hInst)
390 WNDCLASSW wcd;
391 const WCHAR wszDetailsClass[] = { 'D','E','T','A','I','L','S','\0' };
393 memset(&wcd, 0, sizeof(WNDCLASSW));
394 wcd.lpfnWndProc = DetailsProc;
395 wcd.lpszClassName = wszDetailsClass;
396 wcd.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
397 wcd.hCursor = LoadCursorW(0, (LPCWSTR)IDC_ARROW);
399 if(!RegisterClassW(&wcd)) return NULL;
401 globals.hDetails = CreateWindowExW(WS_EX_CLIENTEDGE, wszDetailsClass, NULL,
402 WS_CHILD|WS_VISIBLE, 0, 0, 0, 0, globals.hPaneWnd, NULL, hInst, NULL);
404 return globals.hDetails;