mirror of
https://github.com/reactos/reactos.git
synced 2024-11-20 14:30:57 +00:00
414 lines
9.5 KiB
C
414 lines
9.5 KiB
C
/*
|
|
* PROJECT: ReactOS API Test GUI
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* FILE:
|
|
* PURPOSE: browse dialog implementation
|
|
* COPYRIGHT: Copyright 2008 Ged Murphy <gedmurphy@reactos.org>
|
|
*
|
|
*/
|
|
|
|
#include <precomp.h>
|
|
|
|
#define EXE_SEARCH_DIR L"\\Debug\\testexes\\*"
|
|
#define IL_MAIN 0
|
|
#define IL_TEST 1
|
|
|
|
#define HAS_NO_CHILD 0
|
|
#define HAS_CHILD 1
|
|
|
|
|
|
static INT
|
|
GetNumberOfExesInFolder(LPWSTR lpFolder)
|
|
{
|
|
HANDLE hFind;
|
|
WIN32_FIND_DATAW findFileData;
|
|
INT numFiles = 0;
|
|
|
|
hFind = FindFirstFileW(lpFolder,
|
|
&findFileData);
|
|
if (hFind == INVALID_HANDLE_VALUE)
|
|
{
|
|
DisplayError(GetLastError());
|
|
return 0;
|
|
}
|
|
|
|
do
|
|
{
|
|
if (!(findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
|
{
|
|
numFiles++;
|
|
}
|
|
} while (FindNextFile(hFind, &findFileData) != 0);
|
|
|
|
return numFiles;
|
|
}
|
|
|
|
static INT
|
|
GetListOfTestExes(PMAIN_WND_INFO pInfo)
|
|
{
|
|
HANDLE hFind;
|
|
WIN32_FIND_DATAW findFileData;
|
|
WCHAR szExePath[MAX_PATH];
|
|
LPWSTR ptr;
|
|
INT numFiles = 0;
|
|
INT len;
|
|
|
|
len = GetCurrentDirectoryW(MAX_PATH, szExePath);
|
|
if (!len) return 0;
|
|
|
|
wcsncat(szExePath, EXE_SEARCH_DIR, MAX_PATH - (len + 1));
|
|
|
|
numFiles = GetNumberOfExesInFolder(szExePath);
|
|
if (!numFiles) return 0;
|
|
|
|
pInfo->lpExeList = HeapAlloc(GetProcessHeap(),
|
|
0,
|
|
numFiles * (MAX_PATH * sizeof(WCHAR)));
|
|
if (!pInfo->lpExeList)
|
|
return 0;
|
|
|
|
hFind = FindFirstFileW(szExePath,
|
|
&findFileData);
|
|
if (hFind == INVALID_HANDLE_VALUE)
|
|
{
|
|
DisplayError(GetLastError());
|
|
HeapFree(GetProcessHeap(), 0, pInfo->lpExeList);
|
|
return 0;
|
|
}
|
|
|
|
/* remove the glob */
|
|
ptr = wcschr(szExePath, L'*');
|
|
if (ptr)
|
|
*ptr = L'\0';
|
|
|
|
/* don't modify our base pointer */
|
|
ptr = pInfo->lpExeList;
|
|
|
|
do
|
|
{
|
|
if (!(findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
|
{
|
|
/* set the path */
|
|
wcscpy(ptr, szExePath);
|
|
|
|
/* tag the file onto the path */
|
|
len = MAX_PATH - (wcslen(ptr) + 1);
|
|
wcsncat(ptr, findFileData.cFileName, len);
|
|
|
|
/* move the pointer along by MAX_PATH */
|
|
ptr += MAX_PATH;
|
|
}
|
|
} while (FindNextFile(hFind, &findFileData) != 0);
|
|
|
|
return numFiles;
|
|
}
|
|
|
|
static BOOL
|
|
NodeHasChild(PMAIN_WND_INFO pInfo,
|
|
HTREEITEM hItem)
|
|
{
|
|
TV_ITEM tvItem;
|
|
|
|
tvItem.hItem = hItem;
|
|
tvItem.mask = TVIF_CHILDREN;
|
|
|
|
(void)TreeView_GetItem(pInfo->hBrowseTV, &tvItem);
|
|
|
|
return (tvItem.cChildren == 1);
|
|
}
|
|
|
|
static VOID
|
|
FreeItemTag(PMAIN_WND_INFO pInfo,
|
|
HTREEITEM hItem)
|
|
{
|
|
TV_ITEM tvItem;
|
|
|
|
tvItem.hItem = hItem;
|
|
tvItem.mask = TVIF_PARAM;
|
|
|
|
(void)TreeView_GetItem(pInfo->hBrowseTV, &tvItem);
|
|
|
|
HeapFree(GetProcessHeap(),
|
|
0,
|
|
(PTEST_ITEM)tvItem.lParam);
|
|
}
|
|
|
|
static VOID
|
|
TraverseTreeView(PMAIN_WND_INFO pInfo,
|
|
HTREEITEM hItem)
|
|
{
|
|
while (NodeHasChild(pInfo, hItem))
|
|
{
|
|
HTREEITEM hChildItem;
|
|
|
|
FreeItemTag(pInfo, hItem);
|
|
|
|
hChildItem = TreeView_GetChild(pInfo->hBrowseTV,
|
|
hItem);
|
|
|
|
TraverseTreeView(pInfo,
|
|
hChildItem);
|
|
|
|
hItem = TreeView_GetNextSibling(pInfo->hBrowseTV,
|
|
hItem);
|
|
}
|
|
|
|
if (hItem)
|
|
{
|
|
/* loop the child items and free the tags */
|
|
while (TRUE)
|
|
{
|
|
HTREEITEM hOldItem;
|
|
|
|
FreeItemTag(pInfo, hItem);
|
|
hOldItem = hItem;
|
|
hItem = TreeView_GetNextSibling(pInfo->hBrowseTV,
|
|
hItem);
|
|
if (hItem == NULL)
|
|
{
|
|
hItem = hOldItem;
|
|
break;
|
|
}
|
|
}
|
|
|
|
hItem = TreeView_GetParent(pInfo->hBrowseTV,
|
|
hItem);
|
|
}
|
|
}
|
|
|
|
static HTREEITEM
|
|
InsertIntoTreeView(HWND hTreeView,
|
|
HTREEITEM hRoot,
|
|
LPWSTR lpLabel,
|
|
LPARAM Tag,
|
|
INT Image,
|
|
INT Child)
|
|
{
|
|
TV_ITEM tvi;
|
|
TV_INSERTSTRUCT tvins;
|
|
|
|
ZeroMemory(&tvi, sizeof(tvi));
|
|
ZeroMemory(&tvins, sizeof(tvins));
|
|
|
|
tvi.mask = TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE | TVIF_CHILDREN | TVIF_SELECTEDIMAGE;
|
|
tvi.pszText = lpLabel;
|
|
tvi.cchTextMax = lstrlen(lpLabel);
|
|
tvi.lParam = Tag;
|
|
tvi.iImage = Image;
|
|
tvi.iSelectedImage = Image;
|
|
tvi.cChildren = Child;
|
|
|
|
tvins.item = tvi;
|
|
tvins.hParent = hRoot;
|
|
|
|
return TreeView_InsertItem(hTreeView, &tvins);
|
|
}
|
|
|
|
static PTEST_ITEM
|
|
BuildTestItemData(LPWSTR lpName,
|
|
LPWSTR lpRunCmd)
|
|
{
|
|
PTEST_ITEM pItem;
|
|
|
|
pItem = (PTEST_ITEM)HeapAlloc(GetProcessHeap(),
|
|
0,
|
|
sizeof(TEST_ITEM));
|
|
if (pItem)
|
|
{
|
|
if (lpName)
|
|
{
|
|
wcsncpy(pItem->szName, lpName, MAX_PATH);
|
|
}
|
|
if (lpRunCmd)
|
|
{
|
|
wcsncpy(pItem->szRunCmd, lpRunCmd, MAX_RUN_CMD);
|
|
}
|
|
}
|
|
|
|
return pItem;
|
|
}
|
|
|
|
static VOID
|
|
PopulateTreeView(PMAIN_WND_INFO pInfo)
|
|
{
|
|
HTREEITEM hRoot;
|
|
HIMAGELIST hImgList;
|
|
PTEST_ITEM pTestItem;
|
|
LPWSTR lpExePath;
|
|
LPWSTR lpTestName;
|
|
INT i;
|
|
|
|
pInfo->hBrowseTV = GetDlgItem(pInfo->hBrowseDlg, IDC_TREEVIEW);
|
|
|
|
(void)TreeView_DeleteAllItems(pInfo->hBrowseTV);
|
|
|
|
hImgList = InitImageList(IDI_ICON,
|
|
IDI_TESTS,
|
|
16,
|
|
16);
|
|
if (!hImgList) return;
|
|
|
|
(void)TreeView_SetImageList(pInfo->hBrowseTV,
|
|
hImgList,
|
|
TVSIL_NORMAL);
|
|
|
|
pTestItem = BuildTestItemData(L"Full", L"runall");
|
|
|
|
/* insert the root item into the tree */
|
|
hRoot = InsertIntoTreeView(pInfo->hBrowseTV,
|
|
NULL,
|
|
L"Full",
|
|
(LPARAM)pTestItem,
|
|
IL_MAIN,
|
|
HAS_CHILD);
|
|
|
|
for (i = 0; i < pInfo->numExes; i++)
|
|
{
|
|
HTREEITEM hParent;
|
|
LPWSTR lpStr;
|
|
|
|
lpExePath = pInfo->lpExeList + (MAX_PATH * i);
|
|
|
|
lpTestName = wcsrchr(lpExePath, L'\\');
|
|
if (lpTestName)
|
|
{
|
|
lpTestName++;
|
|
|
|
lpStr = wcschr(lpTestName, L'_');
|
|
if (lpStr)
|
|
{
|
|
//FIXME: Query the test name from the exe directly
|
|
|
|
pTestItem = BuildTestItemData(lpTestName, lpExePath);
|
|
|
|
hParent = InsertIntoTreeView(pInfo->hBrowseTV,
|
|
hRoot,
|
|
lpTestName,
|
|
(LPARAM)pTestItem,
|
|
IL_TEST,
|
|
HAS_CHILD);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (hRoot)
|
|
{
|
|
TreeView_Expand(pInfo->hBrowseTV,
|
|
hRoot,
|
|
TVE_EXPAND);
|
|
}
|
|
}
|
|
|
|
static VOID
|
|
PopulateTestList(PMAIN_WND_INFO pInfo)
|
|
{
|
|
pInfo->numExes = GetListOfTestExes(pInfo);
|
|
if (pInfo->numExes)
|
|
{
|
|
PopulateTreeView(pInfo);
|
|
}
|
|
}
|
|
|
|
static BOOL
|
|
OnInitBrowseDialog(HWND hDlg,
|
|
LPARAM lParam)
|
|
{
|
|
PMAIN_WND_INFO pInfo;
|
|
|
|
pInfo = (PMAIN_WND_INFO)lParam;
|
|
|
|
pInfo->hBrowseDlg = hDlg;
|
|
|
|
SetWindowLongPtr(hDlg,
|
|
GWLP_USERDATA,
|
|
(LONG_PTR)pInfo);
|
|
|
|
PopulateTestList(pInfo);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CALLBACK
|
|
BrowseDlgProc(HWND hDlg,
|
|
UINT Message,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
PMAIN_WND_INFO pInfo;
|
|
|
|
/* Get the window context */
|
|
pInfo = (PMAIN_WND_INFO)GetWindowLongPtr(hDlg,
|
|
GWLP_USERDATA);
|
|
if (pInfo == NULL && Message != WM_INITDIALOG)
|
|
{
|
|
goto HandleDefaultMessage;
|
|
}
|
|
|
|
switch(Message)
|
|
{
|
|
case WM_INITDIALOG:
|
|
return OnInitBrowseDialog(hDlg, lParam);
|
|
|
|
case WM_COMMAND:
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDOK:
|
|
{
|
|
TV_ITEM tvItem;
|
|
|
|
tvItem.hItem = TreeView_GetSelection(pInfo->hBrowseTV);
|
|
tvItem.mask = TVIF_PARAM;
|
|
|
|
if (TreeView_GetItem(pInfo->hBrowseTV, &tvItem))
|
|
{
|
|
PTEST_ITEM pItem;
|
|
|
|
pItem = (PTEST_ITEM)tvItem.lParam;
|
|
if (pItem)
|
|
CopyMemory(&pInfo->SelectedTest, pItem, sizeof(TEST_ITEM));
|
|
|
|
EndDialog(hDlg,
|
|
LOWORD(wParam));
|
|
}
|
|
else
|
|
{
|
|
DisplayMessage(L"Please select an item");
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
case IDCANCEL:
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, pInfo->lpExeList);
|
|
pInfo->lpExeList = NULL;
|
|
|
|
EndDialog(hDlg,
|
|
LOWORD(wParam));
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case WM_DESTROY:
|
|
{
|
|
HTREEITEM hItem = TreeView_GetRoot(pInfo->hBrowseTV);
|
|
|
|
TraverseTreeView(pInfo, hItem);
|
|
|
|
pInfo->hBrowseDlg = NULL;
|
|
|
|
break;
|
|
}
|
|
|
|
HandleDefaultMessage:
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|