1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 2007-2009 Oracle. All rights reserved. 5 * 6 * $Id$ 7 */ 8 9// TpcbUI.cpp : Defines the entry point for the application. 10// 11 12#include <windows.h> 13#include "resource.h" 14#include "TpcbExample.h" 15#include <commctrl.h> 16 17#define MAX_LOADSTRING 100 18 19// Global Variables: 20HINSTANCE hInst; // The current instance 21HWND hWndDlgMain; // Handle to the main dialog window. 22HWND hWndFrame; // Handle to the main window. 23TpcbExample *tpcb; 24 25// Forward declarations of functions included in this code module: 26ATOM MyRegisterClass (HINSTANCE, LPTSTR); 27BOOL InitInstance (HINSTANCE, int); 28LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); 29LRESULT CALLBACK MainDialog (HWND, UINT, WPARAM, LPARAM); 30LRESULT CALLBACK InitDialog (HWND, UINT, WPARAM, LPARAM); 31LRESULT CALLBACK AdvancedDialog (HWND, UINT, WPARAM, LPARAM); 32LRESULT CALLBACK RunDialog (HWND, UINT, WPARAM, LPARAM); 33BOOL GetHomeDirectory(HWND, BOOL); 34BOOL RecursiveDirRemove(wchar_t *); 35 36int WINAPI WinMain( HINSTANCE hInstance, 37 HINSTANCE hPrevInstance, 38 LPTSTR lpCmdLine, 39 int nCmdShow) 40{ 41 MSG msg; 42 HACCEL hAccelTable; 43 44 hWndDlgMain = NULL; 45 // Initialize the tpcb object. 46 tpcb = new TpcbExample(); 47 48 // Perform application initialization: 49 if (!InitInstance (hInstance, nCmdShow)) 50 { 51 return FALSE; 52 } 53 54 hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_WCE_TPCB); 55 56 // Main message loop: 57 while (GetMessage(&msg, NULL, 0, 0)) 58 { 59 if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 60 { 61 TranslateMessage(&msg); 62 DispatchMessage(&msg); 63 } 64 } 65 66 return msg.wParam; 67} 68 69// 70// FUNCTION: MyRegisterClass() 71// 72// PURPOSE: Registers the window class. 73// 74// COMMENTS: 75// 76// It is important to call this function so that the application 77// will get 'well formed' small icons associated with it. 78// 79ATOM MyRegisterClass(HINSTANCE hInstance, LPTSTR szWindowClass) 80{ 81 WNDCLASS wc; 82 83 wc.style = CS_HREDRAW | CS_VREDRAW; 84 wc.lpfnWndProc = (WNDPROC) WndProc; 85 wc.cbClsExtra = 0; 86 wc.cbWndExtra = 0; 87 wc.hInstance = hInstance; 88 wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WCE_TPCB)); 89 wc.hCursor = 0; 90 wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); 91 wc.lpszMenuName = 0; 92 wc.lpszClassName = szWindowClass; 93 94 return RegisterClass(&wc); 95} 96 97// 98// FUNCTION: InitInstance(HANDLE, int) 99// 100// PURPOSE: Saves instance handle and creates main window 101// 102// COMMENTS: 103// 104// In this function, we save the instance handle in a global variable and 105// create and display the main program window. 106// 107BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) 108{ 109 TCHAR szTitle[MAX_LOADSTRING]; // The title bar text 110 TCHAR szWindowClass[MAX_LOADSTRING]; // The window class name 111 112 hInst = hInstance; // Store instance handle in our global variable 113 // Initialize global strings 114 LoadString(hInstance, IDC_WCE_TPCB, szWindowClass, MAX_LOADSTRING); 115 MyRegisterClass(hInstance, szWindowClass); 116 LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); 117 118 hWndFrame = CreateWindow(szWindowClass, szTitle, 119 WS_VISIBLE | WS_MINIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, 120 CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); 121 122 if (!hWndFrame) 123 { 124 return FALSE; 125 } 126 127 ShowWindow(hWndDlgMain, nCmdShow); 128 UpdateWindow(hWndDlgMain); 129 130 return TRUE; 131} 132 133// 134// FUNCTION: WndProc(HWND, unsigned, WORD, LONG) 135// 136// PURPOSE: Processes messages for the main window. 137// 138// WM_COMMAND - process the application menu 139// WM_DESTROY - post a quit message and return 140// 141// 142LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 143{ 144 HWND hDlg; 145 146 switch (message) 147 { 148 case WM_COMMAND: 149 DefWindowProc(hWnd, message, wParam, lParam); 150 break; 151 case WM_CREATE: 152 hDlg = CreateDialog(hInst, 153 MAKEINTRESOURCE(IDD_MAINDIALOG), hWnd, 154 (DLGPROC)MainDialog); 155 break; 156 case WM_DESTROY: 157 PostQuitMessage(0); 158 break; 159 default: 160 return DefWindowProc(hWnd, message, wParam, lParam); 161 } 162 return 0; 163} 164 165// Message handler for the Main dialog box 166LRESULT CALLBACK MainDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) 167{ 168 RECT rt; 169 HWND hCurrentRadioButton; 170 wchar_t wdirname[MAX_PATH], msg[1024], *title; 171 int ret, valid, ntxns, written; 172 173 switch (message) 174 { 175 case WM_INITDIALOG: 176 // maximize the dialog. 177 GetClientRect(GetParent(hDlg), &rt); 178 SetWindowPos(hDlg, HWND_TOP, 0, 0, rt.right, rt.bottom, 179 SWP_SHOWWINDOW); 180 CheckRadioButton(hDlg, IDC_MEDIUM_RADIO, 181 IDC_SMALL_RADIO, IDC_SMALL_RADIO); 182 SetDlgItemText(hDlg, IDC_HOME_EDIT, 183 tpcb->getHomeDirW(wdirname, MAX_PATH)); 184 SetDlgItemInt(hDlg, IDC_TXN_EDIT, 1000, 0); 185 186 SetWindowText(hDlg, L"BDB TPCB Example app"); 187 ShowWindow(hDlg, SW_SHOWNORMAL); 188 return TRUE; 189 case WM_COMMAND: 190 if (LOWORD(wParam) == IDC_INIT_BUTTON || 191 LOWORD(wParam) == IDC_RUN_BUTTON ) { 192 hCurrentRadioButton = GetDlgItem(hDlg, 193 IDC_SMALL_RADIO); 194 if(BST_CHECKED == 195 SendMessage(hCurrentRadioButton, 196 BM_GETCHECK, NULL, NULL)) { 197 tpcb->accounts = 500; 198 tpcb->branches = 10; 199 tpcb->tellers = 50; 200 tpcb->history = 5000; 201 } 202 hCurrentRadioButton = GetDlgItem(hDlg, 203 IDC_MEDIUM_RADIO); 204 if(BST_CHECKED == 205 SendMessage(hCurrentRadioButton, 206 BM_GETCHECK, NULL, NULL)) { 207 tpcb->accounts = 1000; 208 tpcb->branches = 10; 209 tpcb->tellers = 100; 210 tpcb->history = 10000; 211 } 212 hCurrentRadioButton = GetDlgItem(hDlg, 213 IDC_LARGE_RADIO); 214 if(BST_CHECKED == 215 SendMessage(hCurrentRadioButton, 216 BM_GETCHECK, NULL, NULL)) { 217 tpcb->accounts = 100000; 218 tpcb->branches = 10; 219 tpcb->tellers = 100; 220 tpcb->history = 259200; 221 } 222 EnableWindow(GetDlgItem(hDlg, IDC_INIT_BUTTON), 223 FALSE); 224 EnableWindow(GetDlgItem(hDlg, IDC_RUN_BUTTON), 225 FALSE); 226 EnableWindow(GetDlgItem(hDlg, IDC_ADV_BUTTON), 227 FALSE); 228 } 229 if (LOWORD(wParam) == IDC_ADV_BUTTON) { 230 CreateDialog(hInst, 231 MAKEINTRESOURCE(IDD_ADVANCEDDIALOG), hDlg, 232 (DLGPROC)AdvancedDialog); 233 } else if (LOWORD(wParam) == IDC_INIT_BUTTON) { 234 // Close the environment first. 235 // In case this is a re-initialization. 236 tpcb->closeEnv(); 237 GetHomeDirectory(hDlg, TRUE); 238 tpcb->createEnv(0); 239 ret = tpcb->populate(); 240 } else if (LOWORD(wParam) == IDC_RUN_BUTTON) { 241 GetHomeDirectory(hDlg, FALSE); 242 if (GetFileAttributes( 243 tpcb->getHomeDirW(wdirname, MAX_PATH)) != 244 FILE_ATTRIBUTE_DIRECTORY) { 245 _snwprintf(msg, 1024, 246L"Target directory: %s does not exist, or is not a directory.\nMake sure the " 247L"directory name is correct, and that you ran the initialization phase.", 248 wdirname); 249 MessageBox(hDlg, msg, L"Error", MB_OK); 250 EnableWindow(GetDlgItem(hDlg, 251 IDC_INIT_BUTTON), TRUE); 252 EnableWindow(GetDlgItem(hDlg, 253 IDC_RUN_BUTTON), TRUE); 254 EnableWindow(GetDlgItem(hDlg, 255 IDC_ADV_BUTTON), TRUE); 256 return FALSE; 257 } 258 // TODO: Check for an empty directory? 259 ntxns = GetDlgItemInt(hDlg, IDC_TXN_EDIT, 260 &valid, FALSE); 261 if (valid == FALSE) { 262 MessageBox(hDlg, 263 L"Invalid number in transaction field.", 264 L"Error", MB_OK); 265 EnableWindow(GetDlgItem(hDlg, 266 IDC_INIT_BUTTON), TRUE); 267 EnableWindow(GetDlgItem(hDlg, 268 IDC_RUN_BUTTON), TRUE); 269 EnableWindow(GetDlgItem(hDlg, 270 IDC_ADV_BUTTON), TRUE); 271 return FALSE; 272 } 273 tpcb->createEnv(0); 274 ret = tpcb->run(ntxns); 275 } else if (LOWORD(wParam) == IDC_EXIT_BUTTON) { 276 tpcb->closeEnv(); 277 EndDialog(hDlg, LOWORD(wParam)); 278 DestroyWindow(hDlg); 279 DestroyWindow(hWndFrame); 280 return FALSE; 281 } 282 if (LOWORD(wParam) == IDC_INIT_BUTTON || 283 LOWORD(wParam) == IDC_RUN_BUTTON ) { 284 if (ret == 0) 285 title = L"Results"; 286 else 287 title = L"Error message"; 288 written = MultiByteToWideChar(CP_ACP, NULL, 289 tpcb->msgString, strlen(tpcb->msgString), 290 msg, sizeof(msg)/sizeof(msg[0])); 291 msg[written] = L'\0'; 292 MessageBox(hDlg, msg, title, MB_OK); 293 EnableWindow(GetDlgItem(hDlg, IDC_INIT_BUTTON), TRUE); 294 EnableWindow(GetDlgItem(hDlg, IDC_RUN_BUTTON), 295 TRUE); 296 EnableWindow(GetDlgItem(hDlg, IDC_ADV_BUTTON), 297 TRUE); 298 } 299 break; 300 case WM_DESTROY: 301 // Same functionality as WM_COMMAND->IDC_EXIT_BUTTON 302 tpcb->closeEnv(); 303 EndDialog(hDlg, LOWORD(wParam)); 304 DestroyWindow(hDlg); 305 DestroyWindow(hWndFrame); 306 return FALSE; 307 default: 308 return DefWindowProc(hDlg, message, wParam, lParam); 309 } 310 return TRUE; 311} 312 313// Message handler for the Advanced dialog box 314LRESULT CALLBACK AdvancedDialog(HWND hDlg, UINT message, 315 WPARAM wParam, LPARAM lParam) 316{ 317 RECT rt; 318 HWND hCurrentCheckBox; 319 int currentInt, valid; 320 321 switch (message) 322 { 323 case WM_INITDIALOG: 324 GetClientRect(GetParent(hDlg), &rt); 325 SetWindowPos(hDlg, HWND_TOP, 0, 0, rt.right, rt.bottom, 326 SWP_SHOWWINDOW); 327 if (tpcb->fast_mode == 0) { 328 hCurrentCheckBox = 329 GetDlgItem(hDlg, IDC_FASTMODE_CHECK); 330 SendMessage(hCurrentCheckBox, BM_SETCHECK, 331 BST_CHECKED, 0); 332 } 333 if (tpcb->verbose == 1) { 334 hCurrentCheckBox = 335 GetDlgItem(hDlg, IDC_VERBOSE_CHECK); 336 SendMessage(hCurrentCheckBox, BM_SETCHECK, 337 BST_CHECKED, 0); 338 } 339 if (tpcb->cachesize != 0) { 340 SetDlgItemInt(hDlg, IDC_CACHE_EDIT, 341 tpcb->cachesize/1024, FALSE); 342 } 343 break; 344 case WM_COMMAND: 345 if (LOWORD(wParam) == IDC_DONE_BUTTON) { 346 hCurrentCheckBox = 347 GetDlgItem(hDlg, IDC_FASTMODE_CHECK); 348 if(BST_CHECKED == SendMessage(hCurrentCheckBox, 349 BM_GETCHECK, NULL, NULL)) 350 tpcb->fast_mode = 0; 351 else 352 tpcb->fast_mode = 1; 353 hCurrentCheckBox = 354 GetDlgItem(hDlg, IDC_VERBOSE_CHECK); 355 if(BST_CHECKED == SendMessage(hCurrentCheckBox, 356 BM_GETCHECK, NULL, NULL)) 357 tpcb->verbose = 1; 358 else 359 tpcb->verbose = 0; 360 currentInt = GetDlgItemInt(hDlg, 361 IDC_RANDOM_EDIT, &valid, FALSE); 362 if (valid != FALSE) 363 tpcb->rand_seed = currentInt; 364 currentInt = GetDlgItemInt(hDlg, 365 IDC_CACHE_EDIT, &valid, FALSE); 366 if (valid != FALSE) { 367 if (currentInt < 20) { 368 MessageBox(hDlg, 369 L"Min cache size is 20kb.", 370 L"Error", MB_OK); 371 return FALSE; 372 } 373 tpcb->cachesize = currentInt*1024; 374 } 375 EndDialog(hDlg, LOWORD(wParam)); 376 DestroyWindow(hDlg); 377 } 378 break; 379 default: 380 return DefWindowProc(hDlg, message, wParam, lParam); 381 } 382 return TRUE; 383} 384 385// Utility function to retrieve the directory name 386// from the control, and set it in the tpcb object. 387// Optionally remove and create requested directory. 388BOOL 389GetHomeDirectory(HWND hDlg, BOOL init) 390{ 391 wchar_t wdirname[MAX_PATH]; 392 DWORD attrs; 393 394 if (GetDlgItemText(hDlg, IDC_HOME_EDIT, wdirname, MAX_PATH) == 0) 395 tpcb->setHomeDir(TESTDIR); 396 else 397 tpcb->setHomeDirW(wdirname); 398 399 if (init == TRUE) { 400 // Ensure that wdirname holds the correct version: 401 tpcb->getHomeDirW(wdirname, MAX_PATH); 402 403 // If the directory exists, ensure that it is empty. 404 attrs = GetFileAttributes(wdirname); 405 if (attrs == FILE_ATTRIBUTE_DIRECTORY) 406 RecursiveDirRemove(wdirname); 407 else if (attrs == FILE_ATTRIBUTE_NORMAL) 408 DeleteFile(wdirname); 409 else if (attrs != 0xFFFFFFFF) { 410 // Not a directory or normal file, don't try to remove 411 // it, or create a new directory over the top. 412 return FALSE; 413 } 414 415 // Create the requested directory. 416 return CreateDirectory(wdirname, NULL); 417 } 418 return TRUE; 419} 420 421BOOL 422RecursiveDirRemove(wchar_t *dirname) 423{ 424 HANDLE hFind; // file handle 425 WIN32_FIND_DATA findFileData; 426 427 wchar_t DirPath[MAX_PATH]; 428 wchar_t FileName[MAX_PATH]; 429 430 wcscpy(DirPath, dirname); 431 wcscat(DirPath, L"\\*"); // searching all files 432 wcscpy(FileName, dirname); 433 wcscat(FileName, L"\\"); 434 435 MessageBox(hWndDlgMain, L"Cleaning directory.", L"Message", MB_OK); 436 // find the first file 437 if ((hFind = FindFirstFile(DirPath,&findFileData)) == 438 INVALID_HANDLE_VALUE) 439 return FALSE; 440 441 wcscpy(DirPath,FileName); 442 MessageBox(hWndDlgMain, L"Found files in directory.", 443 L"Message", MB_OK); 444 445 bool bSearch = true; 446 do { 447 448 wcscpy(FileName + wcslen(DirPath), findFileData.cFileName); 449 if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 450 { 451 // we have found a directory, recurse 452 if (!RecursiveDirRemove(FileName)) 453 break; // directory couldn't be deleted 454 } else { 455 if (findFileData.dwFileAttributes & 456 FILE_ATTRIBUTE_READONLY) 457 SetFileAttributes(findFileData.cFileName, 458 FILE_ATTRIBUTE_NORMAL); 459 if (!DeleteFile(FileName)) { 460 MessageBox(hWndDlgMain, L"Delete failed.", 461 L"Message", MB_OK); 462 break; // file couldn't be deleted 463 } 464 } 465 } while (FindNextFile(hFind,&findFileData)); 466 467 FindClose(hFind); // closing file handle 468 return RemoveDirectory(dirname); // remove the empty directory 469} 470 471// Callback function used to receive error messages from DB 472// Needs to have a C calling convention. 473// Using this function, since the implementation is presenting 474// the error to the user in a message box. 475extern "C" { 476void tpcb_errcallback(const DB_ENV *, const char *errpfx, const char *errstr) 477{ 478 wchar_t wstr[ERR_STRING_MAX]; 479 memset(wstr, 0, sizeof(wstr)); 480 MultiByteToWideChar(CP_ACP, 0, errstr, strlen(errstr), 481 wstr, ERR_STRING_MAX-1); 482 MessageBox(hWndDlgMain, wstr, L"Error Message", MB_OK); 483 exit(1); 484} 485} 486 487