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