/*- * See the file LICENSE for redistribution information. * * Copyright (c) 2007-2009 Oracle. All rights reserved. * * $Id$ */ // TpcbUI.cpp : Defines the entry point for the application. // #include #include "resource.h" #include "TpcbExample.h" #include #define MAX_LOADSTRING 100 // Global Variables: HINSTANCE hInst; // The current instance HWND hWndDlgMain; // Handle to the main dialog window. HWND hWndFrame; // Handle to the main window. TpcbExample *tpcb; // Forward declarations of functions included in this code module: ATOM MyRegisterClass (HINSTANCE, LPTSTR); BOOL InitInstance (HINSTANCE, int); LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK MainDialog (HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK InitDialog (HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK AdvancedDialog (HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK RunDialog (HWND, UINT, WPARAM, LPARAM); BOOL GetHomeDirectory(HWND, BOOL); BOOL RecursiveDirRemove(wchar_t *); int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { MSG msg; HACCEL hAccelTable; hWndDlgMain = NULL; // Initialize the tpcb object. tpcb = new TpcbExample(); // Perform application initialization: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_WCE_TPCB); // Main message loop: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return msg.wParam; } // // FUNCTION: MyRegisterClass() // // PURPOSE: Registers the window class. // // COMMENTS: // // It is important to call this function so that the application // will get 'well formed' small icons associated with it. // ATOM MyRegisterClass(HINSTANCE hInstance, LPTSTR szWindowClass) { WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = (WNDPROC) WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WCE_TPCB)); wc.hCursor = 0; wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); wc.lpszMenuName = 0; wc.lpszClassName = szWindowClass; return RegisterClass(&wc); } // // FUNCTION: InitInstance(HANDLE, int) // // PURPOSE: Saves instance handle and creates main window // // COMMENTS: // // In this function, we save the instance handle in a global variable and // create and display the main program window. // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { TCHAR szTitle[MAX_LOADSTRING]; // The title bar text TCHAR szWindowClass[MAX_LOADSTRING]; // The window class name hInst = hInstance; // Store instance handle in our global variable // Initialize global strings LoadString(hInstance, IDC_WCE_TPCB, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance, szWindowClass); LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); hWndFrame = CreateWindow(szWindowClass, szTitle, WS_VISIBLE | WS_MINIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); if (!hWndFrame) { return FALSE; } ShowWindow(hWndDlgMain, nCmdShow); UpdateWindow(hWndDlgMain); return TRUE; } // // FUNCTION: WndProc(HWND, unsigned, WORD, LONG) // // PURPOSE: Processes messages for the main window. // // WM_COMMAND - process the application menu // WM_DESTROY - post a quit message and return // // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { HWND hDlg; switch (message) { case WM_COMMAND: DefWindowProc(hWnd, message, wParam, lParam); break; case WM_CREATE: hDlg = CreateDialog(hInst, MAKEINTRESOURCE(IDD_MAINDIALOG), hWnd, (DLGPROC)MainDialog); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } // Message handler for the Main dialog box LRESULT CALLBACK MainDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { RECT rt; HWND hCurrentRadioButton; wchar_t wdirname[MAX_PATH], msg[1024], *title; int ret, valid, ntxns, written; switch (message) { case WM_INITDIALOG: // maximize the dialog. GetClientRect(GetParent(hDlg), &rt); SetWindowPos(hDlg, HWND_TOP, 0, 0, rt.right, rt.bottom, SWP_SHOWWINDOW); CheckRadioButton(hDlg, IDC_MEDIUM_RADIO, IDC_SMALL_RADIO, IDC_SMALL_RADIO); SetDlgItemText(hDlg, IDC_HOME_EDIT, tpcb->getHomeDirW(wdirname, MAX_PATH)); SetDlgItemInt(hDlg, IDC_TXN_EDIT, 1000, 0); SetWindowText(hDlg, L"BDB TPCB Example app"); ShowWindow(hDlg, SW_SHOWNORMAL); return TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDC_INIT_BUTTON || LOWORD(wParam) == IDC_RUN_BUTTON ) { hCurrentRadioButton = GetDlgItem(hDlg, IDC_SMALL_RADIO); if(BST_CHECKED == SendMessage(hCurrentRadioButton, BM_GETCHECK, NULL, NULL)) { tpcb->accounts = 500; tpcb->branches = 10; tpcb->tellers = 50; tpcb->history = 5000; } hCurrentRadioButton = GetDlgItem(hDlg, IDC_MEDIUM_RADIO); if(BST_CHECKED == SendMessage(hCurrentRadioButton, BM_GETCHECK, NULL, NULL)) { tpcb->accounts = 1000; tpcb->branches = 10; tpcb->tellers = 100; tpcb->history = 10000; } hCurrentRadioButton = GetDlgItem(hDlg, IDC_LARGE_RADIO); if(BST_CHECKED == SendMessage(hCurrentRadioButton, BM_GETCHECK, NULL, NULL)) { tpcb->accounts = 100000; tpcb->branches = 10; tpcb->tellers = 100; tpcb->history = 259200; } EnableWindow(GetDlgItem(hDlg, IDC_INIT_BUTTON), FALSE); EnableWindow(GetDlgItem(hDlg, IDC_RUN_BUTTON), FALSE); EnableWindow(GetDlgItem(hDlg, IDC_ADV_BUTTON), FALSE); } if (LOWORD(wParam) == IDC_ADV_BUTTON) { CreateDialog(hInst, MAKEINTRESOURCE(IDD_ADVANCEDDIALOG), hDlg, (DLGPROC)AdvancedDialog); } else if (LOWORD(wParam) == IDC_INIT_BUTTON) { // Close the environment first. // In case this is a re-initialization. tpcb->closeEnv(); GetHomeDirectory(hDlg, TRUE); tpcb->createEnv(0); ret = tpcb->populate(); } else if (LOWORD(wParam) == IDC_RUN_BUTTON) { GetHomeDirectory(hDlg, FALSE); if (GetFileAttributes( tpcb->getHomeDirW(wdirname, MAX_PATH)) != FILE_ATTRIBUTE_DIRECTORY) { _snwprintf(msg, 1024, L"Target directory: %s does not exist, or is not a directory.\nMake sure the " L"directory name is correct, and that you ran the initialization phase.", wdirname); MessageBox(hDlg, msg, L"Error", MB_OK); EnableWindow(GetDlgItem(hDlg, IDC_INIT_BUTTON), TRUE); EnableWindow(GetDlgItem(hDlg, IDC_RUN_BUTTON), TRUE); EnableWindow(GetDlgItem(hDlg, IDC_ADV_BUTTON), TRUE); return FALSE; } // TODO: Check for an empty directory? ntxns = GetDlgItemInt(hDlg, IDC_TXN_EDIT, &valid, FALSE); if (valid == FALSE) { MessageBox(hDlg, L"Invalid number in transaction field.", L"Error", MB_OK); EnableWindow(GetDlgItem(hDlg, IDC_INIT_BUTTON), TRUE); EnableWindow(GetDlgItem(hDlg, IDC_RUN_BUTTON), TRUE); EnableWindow(GetDlgItem(hDlg, IDC_ADV_BUTTON), TRUE); return FALSE; } tpcb->createEnv(0); ret = tpcb->run(ntxns); } else if (LOWORD(wParam) == IDC_EXIT_BUTTON) { tpcb->closeEnv(); EndDialog(hDlg, LOWORD(wParam)); DestroyWindow(hDlg); DestroyWindow(hWndFrame); return FALSE; } if (LOWORD(wParam) == IDC_INIT_BUTTON || LOWORD(wParam) == IDC_RUN_BUTTON ) { if (ret == 0) title = L"Results"; else title = L"Error message"; written = MultiByteToWideChar(CP_ACP, NULL, tpcb->msgString, strlen(tpcb->msgString), msg, sizeof(msg)/sizeof(msg[0])); msg[written] = L'\0'; MessageBox(hDlg, msg, title, MB_OK); EnableWindow(GetDlgItem(hDlg, IDC_INIT_BUTTON), TRUE); EnableWindow(GetDlgItem(hDlg, IDC_RUN_BUTTON), TRUE); EnableWindow(GetDlgItem(hDlg, IDC_ADV_BUTTON), TRUE); } break; case WM_DESTROY: // Same functionality as WM_COMMAND->IDC_EXIT_BUTTON tpcb->closeEnv(); EndDialog(hDlg, LOWORD(wParam)); DestroyWindow(hDlg); DestroyWindow(hWndFrame); return FALSE; default: return DefWindowProc(hDlg, message, wParam, lParam); } return TRUE; } // Message handler for the Advanced dialog box LRESULT CALLBACK AdvancedDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { RECT rt; HWND hCurrentCheckBox; int currentInt, valid; switch (message) { case WM_INITDIALOG: GetClientRect(GetParent(hDlg), &rt); SetWindowPos(hDlg, HWND_TOP, 0, 0, rt.right, rt.bottom, SWP_SHOWWINDOW); if (tpcb->fast_mode == 0) { hCurrentCheckBox = GetDlgItem(hDlg, IDC_FASTMODE_CHECK); SendMessage(hCurrentCheckBox, BM_SETCHECK, BST_CHECKED, 0); } if (tpcb->verbose == 1) { hCurrentCheckBox = GetDlgItem(hDlg, IDC_VERBOSE_CHECK); SendMessage(hCurrentCheckBox, BM_SETCHECK, BST_CHECKED, 0); } if (tpcb->cachesize != 0) { SetDlgItemInt(hDlg, IDC_CACHE_EDIT, tpcb->cachesize/1024, FALSE); } break; case WM_COMMAND: if (LOWORD(wParam) == IDC_DONE_BUTTON) { hCurrentCheckBox = GetDlgItem(hDlg, IDC_FASTMODE_CHECK); if(BST_CHECKED == SendMessage(hCurrentCheckBox, BM_GETCHECK, NULL, NULL)) tpcb->fast_mode = 0; else tpcb->fast_mode = 1; hCurrentCheckBox = GetDlgItem(hDlg, IDC_VERBOSE_CHECK); if(BST_CHECKED == SendMessage(hCurrentCheckBox, BM_GETCHECK, NULL, NULL)) tpcb->verbose = 1; else tpcb->verbose = 0; currentInt = GetDlgItemInt(hDlg, IDC_RANDOM_EDIT, &valid, FALSE); if (valid != FALSE) tpcb->rand_seed = currentInt; currentInt = GetDlgItemInt(hDlg, IDC_CACHE_EDIT, &valid, FALSE); if (valid != FALSE) { if (currentInt < 20) { MessageBox(hDlg, L"Min cache size is 20kb.", L"Error", MB_OK); return FALSE; } tpcb->cachesize = currentInt*1024; } EndDialog(hDlg, LOWORD(wParam)); DestroyWindow(hDlg); } break; default: return DefWindowProc(hDlg, message, wParam, lParam); } return TRUE; } // Utility function to retrieve the directory name // from the control, and set it in the tpcb object. // Optionally remove and create requested directory. BOOL GetHomeDirectory(HWND hDlg, BOOL init) { wchar_t wdirname[MAX_PATH]; DWORD attrs; if (GetDlgItemText(hDlg, IDC_HOME_EDIT, wdirname, MAX_PATH) == 0) tpcb->setHomeDir(TESTDIR); else tpcb->setHomeDirW(wdirname); if (init == TRUE) { // Ensure that wdirname holds the correct version: tpcb->getHomeDirW(wdirname, MAX_PATH); // If the directory exists, ensure that it is empty. attrs = GetFileAttributes(wdirname); if (attrs == FILE_ATTRIBUTE_DIRECTORY) RecursiveDirRemove(wdirname); else if (attrs == FILE_ATTRIBUTE_NORMAL) DeleteFile(wdirname); else if (attrs != 0xFFFFFFFF) { // Not a directory or normal file, don't try to remove // it, or create a new directory over the top. return FALSE; } // Create the requested directory. return CreateDirectory(wdirname, NULL); } return TRUE; } BOOL RecursiveDirRemove(wchar_t *dirname) { HANDLE hFind; // file handle WIN32_FIND_DATA findFileData; wchar_t DirPath[MAX_PATH]; wchar_t FileName[MAX_PATH]; wcscpy(DirPath, dirname); wcscat(DirPath, L"\\*"); // searching all files wcscpy(FileName, dirname); wcscat(FileName, L"\\"); MessageBox(hWndDlgMain, L"Cleaning directory.", L"Message", MB_OK); // find the first file if ((hFind = FindFirstFile(DirPath,&findFileData)) == INVALID_HANDLE_VALUE) return FALSE; wcscpy(DirPath,FileName); MessageBox(hWndDlgMain, L"Found files in directory.", L"Message", MB_OK); bool bSearch = true; do { wcscpy(FileName + wcslen(DirPath), findFileData.cFileName); if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { // we have found a directory, recurse if (!RecursiveDirRemove(FileName)) break; // directory couldn't be deleted } else { if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) SetFileAttributes(findFileData.cFileName, FILE_ATTRIBUTE_NORMAL); if (!DeleteFile(FileName)) { MessageBox(hWndDlgMain, L"Delete failed.", L"Message", MB_OK); break; // file couldn't be deleted } } } while (FindNextFile(hFind,&findFileData)); FindClose(hFind); // closing file handle return RemoveDirectory(dirname); // remove the empty directory } // Callback function used to receive error messages from DB // Needs to have a C calling convention. // Using this function, since the implementation is presenting // the error to the user in a message box. extern "C" { void tpcb_errcallback(const DB_ENV *, const char *errpfx, const char *errstr) { wchar_t wstr[ERR_STRING_MAX]; memset(wstr, 0, sizeof(wstr)); MultiByteToWideChar(CP_ACP, 0, errstr, strlen(errstr), wstr, ERR_STRING_MAX-1); MessageBox(hWndDlgMain, wstr, L"Error Message", MB_OK); exit(1); } }