1
0

configDlg.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. #include ".\configdlg.h"
  2. #include ".\smtpdlg.h"
  3. #include ".\resource.h"
  4. #include <shlobj.h>
  5. #include ".\miniVersion.h"
  6. #include ".\getwinver.h"
  7. #include ".\settings.h"
  8. #include ".\minidump.h"
  9. #include ".\main.h"
  10. #include <strsafe.h>
  11. #include "api__gen_crasher.h"
  12. extern Settings settings;
  13. BOOL CALLBACK ConfigDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  14. {
  15. static wchar_t *path;
  16. switch (uMsg)
  17. {
  18. case WM_INITDIALOG:
  19. {
  20. HWND hwCombo = GetDlgItem(hwndDlg, IDC_CMB_DMPTYPE);
  21. // detect windows version
  22. wchar_t strBuff[2048] = {0}, winVer[32] = {0}, build[32] = {0};
  23. int nWinVer = 0;
  24. GetWinVer(winVer, &nWinVer, build);
  25. StringCchPrintf(strBuff, 2048, L"%s (%s)", winVer, build);
  26. SetWindowText(GetDlgItem(hwndDlg, IDC_LBL_OSVERSION), strBuff);
  27. // discover dbghlp.dll
  28. HMODULE hm = NULL;
  29. // first in app folder
  30. if (GetModuleFileName( NULL, strBuff, _MAX_PATH ))
  31. {
  32. wchar_t *pSlash = wcsrchr( strBuff, L'\\' );
  33. if (pSlash)
  34. {
  35. StringCchCopy(pSlash+1, 2048 - (pSlash + 1 - strBuff), L"dbghelp.dll" );
  36. hm = LoadLibraryW( strBuff );
  37. }
  38. }
  39. if (!hm)
  40. {
  41. // load any version we can
  42. hm = LoadLibraryW(L"dbghelp.dll");
  43. }
  44. if (hm)
  45. {
  46. GetModuleFileName(hm, strBuff, 2048);
  47. SetWindowText(GetDlgItem(hwndDlg, IDC_LBL_DLLPATH), strBuff);
  48. // try to get dll version
  49. CMiniVersion ver(strBuff);
  50. if(ver.Init())
  51. {
  52. WORD dwBuf[4] = {0};
  53. ver.GetProductVersion(dwBuf);
  54. StringCchPrintf(strBuff, 2048, L"%d.%d.%d.%d", dwBuf[0], dwBuf[1], dwBuf[2], dwBuf[3]);
  55. }
  56. else
  57. {
  58. WASABI_API_LNGSTRINGW_BUF(IDS_UNABLE_TO_LOAD, strBuff, 128);
  59. }
  60. ver.Release();
  61. BOOL (WINAPI* MiniDumpWriteDump)(
  62. HANDLE hProcess,
  63. DWORD ProcessId,
  64. HANDLE hFile,
  65. MINIDUMP_TYPE DumpType,
  66. PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
  67. PMINIDUMP_EXCEPTION_INFORMATION UserStreamParam,
  68. PMINIDUMP_EXCEPTION_INFORMATION CallbackParam
  69. ) = NULL;
  70. *(FARPROC*)&MiniDumpWriteDump = GetProcAddress(hm, "MiniDumpWriteDump");
  71. wchar_t temp[256] = {0};
  72. StringCchPrintfW(temp, 256, L"%s [%s]", strBuff, WASABI_API_LNGSTRINGW(MiniDumpWriteDump ? IDS_LOADED_OK : IDS_UNABLE_TO_LOAD));
  73. SetDlgItemText(hwndDlg, IDC_LBL_DLLVERSION, temp);
  74. FreeLibrary(hm);
  75. }
  76. else
  77. {
  78. SetWindowText(GetDlgItem(hwndDlg, IDC_LBL_DLLPATH), WASABI_API_LNGSTRINGW(IDS_NOT_FOUND));
  79. wchar_t temp[256] = {0}, temp2[128] = {0};
  80. StringCchPrintfW(temp, 256, L"%s [%s]", WASABI_API_LNGSTRINGW(IDS_UNKNOWN), WASABI_API_LNGSTRINGW_BUF(IDS_UNABLE_TO_LOAD, temp2, 128));
  81. SetWindowText(GetDlgItem(hwndDlg, IDC_LBL_DLLVERSION), temp);
  82. }
  83. // set combobox with values
  84. WPARAM pos;
  85. pos = SendMessage(hwCombo, CB_ADDSTRING, 0, (LPARAM) L"MiniDumpNormal");
  86. SendMessage(hwCombo, CB_SETITEMDATA, pos, 0x00000000);
  87. pos = SendMessage(hwCombo, CB_ADDSTRING, 0, (LPARAM) L"MiniDumpWithDataSegs");
  88. SendMessage(hwCombo, CB_SETITEMDATA, pos, 0x00000001);
  89. pos = SendMessage(hwCombo, CB_ADDSTRING, 0, (LPARAM) L"MiniDumpWithFullMemory");
  90. SendMessage(hwCombo, CB_SETITEMDATA, pos, 0x00000002);
  91. pos = SendMessage(hwCombo, CB_ADDSTRING, 0, (LPARAM) L"MiniDumpWithHandleData (Not Supported: Windows Me/98/95)");
  92. SendMessage(hwCombo, CB_SETITEMDATA, pos, 0x00000004);
  93. pos = SendMessage(hwCombo, CB_ADDSTRING, 0, (LPARAM) L"MiniDumpFilterMemory");
  94. SendMessage(hwCombo, CB_SETITEMDATA, pos, 0x00000008);
  95. pos = SendMessage(hwCombo, CB_ADDSTRING, 0, (LPARAM) L"MiniDumpScanMemory");
  96. SendMessage(hwCombo, CB_SETITEMDATA, pos, 0x00000010);
  97. pos = SendMessage(hwCombo, CB_ADDSTRING, 0, (LPARAM) L"MiniDumpWithUnloadedModules (Not Supported: DbgHelp 5.1 and earlier)");
  98. SendMessage(hwCombo, CB_SETITEMDATA, pos, 0x00000020);
  99. pos = SendMessage(hwCombo, CB_ADDSTRING, 0, (LPARAM) L"MiniDumpWithIndirectlyReferencedMemory (Not Supported: DbgHelp 5.1 and earlier)");
  100. SendMessage(hwCombo, CB_SETITEMDATA, pos, 0x00000040);
  101. pos = SendMessage(hwCombo, CB_ADDSTRING, 0, (LPARAM) L"MiniDumpFilterModulePaths (Not Supported: DbgHelp 5.1 and earlier)");
  102. SendMessage(hwCombo, CB_SETITEMDATA, pos, 0x00000080);
  103. pos = SendMessage(hwCombo, CB_ADDSTRING, 0, (LPARAM) L"MiniDumpWithProcessThreadData (Not Supported: DbgHelp 5.1 and earlier)");
  104. SendMessage(hwCombo, CB_SETITEMDATA, pos, 0x00000100);
  105. pos = SendMessage(hwCombo, CB_ADDSTRING, 0, (LPARAM) L"MiniDumpWithPrivateReadWriteMemory (Not Supported: DbgHelp 5.1 and earlier)");
  106. SendMessage(hwCombo, CB_SETITEMDATA, pos, 0x00000200);
  107. pos = SendMessage(hwCombo, CB_ADDSTRING, 0, (LPARAM) L"MiniDumpWithoutOptionalData (Not Supported: DbgHelp 6.1 and earlier)");
  108. SendMessage(hwCombo, CB_SETITEMDATA, pos, 0x00000400);
  109. pos = SendMessage(hwCombo, CB_ADDSTRING, 0, (LPARAM) L"MiniDumpWithFullMemoryInfo (Not Supported: DbgHelp 6.1 and earlier)");
  110. SendMessage(hwCombo, CB_SETITEMDATA, pos, 0x00000800);
  111. pos = SendMessage(hwCombo, CB_ADDSTRING, 0, (LPARAM) L"MiniDumpWithThreadInfo (Not Supported: DbgHelp 6.1 and earlier)");
  112. SendMessage(hwCombo, CB_SETITEMDATA, pos, 0x00001000);
  113. pos = SendMessage(hwCombo, CB_ADDSTRING, 0, (LPARAM) L"MiniDumpWithCodeSegs (Not Supported: DbgHelp 6.1 and earlier)");
  114. SendMessage(hwCombo, CB_SETITEMDATA, pos, 0x00002000);
  115. // read settings
  116. settings.Load();
  117. CheckDlgButton(hwndDlg, IDC_CHK_CREATELOG, settings.createLOG);
  118. CheckDlgButton(hwndDlg, IDC_CHK_CREATEDMP, settings.createDMP);
  119. CheckDlgButton(hwndDlg, IDC_CHK_RESTART, settings.autoRestart);
  120. CheckDlgButton(hwndDlg, IDC_CHK_SILENT, settings.silentMode);
  121. CheckDlgButton(hwndDlg, IDC_CHK_SEND, settings.sendData);
  122. CheckDlgButton(hwndDlg, IDC_CHK_COMPRESS, settings.zipData);
  123. CheckDlgButton(hwndDlg, IDC_RB_USECLIENT, settings.sendByClient);
  124. CheckDlgButton(hwndDlg, IDC_RB_USESMTP, settings.sendBySMTP);
  125. CreatePathFromFullName(&path, settings.zipPath);
  126. SetWindowText(GetDlgItem(hwndDlg, IDC_EDT_PATH), path);
  127. SetWindowText(GetDlgItem(hwndDlg, IDC_EDT_ZIPNAME), GetFileName(settings.zipPath));
  128. SelectComboBoxItem(hwCombo, settings.dumpType);
  129. SetWindowText(GetDlgItem(hwndDlg, IDC_EDT_DMPPATH), GetFileName(settings.dumpPath));
  130. CheckDlgButton(hwndDlg, IDC_CHK_LOGSYSTEM, settings.logSystem);
  131. CheckDlgButton(hwndDlg, IDC_CHK_LOGREGISTRY, settings.logRegistry);
  132. CheckDlgButton(hwndDlg, IDC_CHK_LOGSTACK, settings.logStack);
  133. CheckDlgButton(hwndDlg, IDC_CHK_LOGMODULE, settings.logModule);
  134. SetWindowText(GetDlgItem(hwndDlg, IDC_EDT_LOGPATH), GetFileName(settings.logPath));
  135. UpdateSend(hwndDlg, settings.sendData);
  136. UpdateZip(hwndDlg, settings.zipData);
  137. UpdateCreateDmp(hwndDlg, settings.createDMP);
  138. UpdateCreateLog(hwndDlg, settings.createLOG);
  139. }
  140. break;
  141. case WM_DESTROY:
  142. {
  143. wchar_t buf[1024] = {0};
  144. int len, pathlen;
  145. HWND hwCombo;
  146. settings.createLOG = (SendMessage(GetDlgItem(hwndDlg, IDC_CHK_CREATELOG), BM_GETCHECK, 0,0) == BST_CHECKED);
  147. settings.createDMP = (SendMessage(GetDlgItem(hwndDlg, IDC_CHK_CREATEDMP), BM_GETCHECK, 0,0) == BST_CHECKED);
  148. settings.autoRestart = (SendMessage(GetDlgItem(hwndDlg, IDC_CHK_RESTART), BM_GETCHECK, 0,0) == BST_CHECKED);
  149. settings.silentMode = (SendMessage(GetDlgItem(hwndDlg, IDC_CHK_SILENT), BM_GETCHECK, 0,0) == BST_CHECKED);
  150. settings.sendData = (SendMessage(GetDlgItem(hwndDlg, IDC_CHK_SEND), BM_GETCHECK, 0,0) == BST_CHECKED);
  151. settings.sendByClient = (SendMessage(GetDlgItem(hwndDlg, IDC_RB_USECLIENT), BM_GETCHECK, 0,0) == BST_CHECKED);
  152. settings.sendBySMTP = !settings.sendByClient;
  153. settings.zipData = (SendMessage(GetDlgItem(hwndDlg, IDC_CHK_COMPRESS), BM_GETCHECK, 0,0) == BST_CHECKED);
  154. len = GetWindowText(GetDlgItem(hwndDlg, IDC_EDT_PATH), buf, 1024);
  155. if (path) free(path);
  156. path = NULL;
  157. if (len)
  158. {
  159. int cpyLen;
  160. path = (wchar_t*)malloc((len +1)*2);
  161. cpyLen = (buf[len-1] == L'\\') ? len -1: len;
  162. StringCchCopyN(path, len + 1, buf, cpyLen);
  163. }
  164. pathlen = (path) ? (int)lstrlen(path) + 1 : 0;
  165. if (settings.zipPath) free(settings.zipPath);
  166. settings.zipPath = NULL;
  167. len = GetWindowText(GetDlgItem(hwndDlg, IDC_EDT_ZIPNAME), buf, 1024);
  168. if (len)
  169. {
  170. if (pathlen)
  171. {
  172. len += pathlen;
  173. settings.zipPath = (wchar_t*)malloc((len + 1)*2);
  174. StringCchPrintf(settings.zipPath, len+1, L"%s\\%s", path, buf);
  175. }
  176. else
  177. {
  178. settings.zipPath = (wchar_t*)malloc((len + 1)*2);
  179. StringCchCopy(settings.zipPath, len+1, buf);
  180. }
  181. }
  182. else // because path is based on the zipPath just write path
  183. {
  184. if (pathlen)
  185. {
  186. len = pathlen;
  187. settings.zipPath = (wchar_t*)malloc((len + 1)*2);
  188. StringCchPrintf(settings.zipPath, len+1, L"%s\\", path);
  189. }
  190. }
  191. hwCombo = GetDlgItem(hwndDlg, IDC_CMB_DMPTYPE);
  192. settings.dumpType = (int) SendMessage(hwCombo, CB_GETITEMDATA, SendMessage(hwCombo, CB_GETCURSEL, 0, 0), 0);
  193. if (settings.dumpPath) free(settings.dumpPath);
  194. settings.dumpPath = NULL;
  195. len = GetWindowText(GetDlgItem(hwndDlg, IDC_EDT_DMPNAME), buf, 1024);
  196. if (len)
  197. {
  198. if (pathlen)
  199. {
  200. len += pathlen;
  201. settings.dumpPath = (wchar_t*)malloc((len + 1)*2);
  202. StringCchPrintf(settings.dumpPath, len+1, L"%s\\%s", path, buf);
  203. }
  204. else
  205. {
  206. settings.dumpPath = (wchar_t*)malloc((len + 1)*2);
  207. StringCchCopy(settings.dumpPath, len+1, buf);
  208. }
  209. }
  210. settings.logSystem = (SendMessage(GetDlgItem(hwndDlg, IDC_CHK_LOGSYSTEM), BM_GETCHECK, 0,0) == BST_CHECKED);
  211. settings.logRegistry = (SendMessage(GetDlgItem(hwndDlg, IDC_CHK_LOGREGISTRY), BM_GETCHECK, 0,0) == BST_CHECKED);
  212. settings.logStack = (SendMessage(GetDlgItem(hwndDlg, IDC_CHK_LOGSTACK), BM_GETCHECK, 0,0) == BST_CHECKED);
  213. settings.logModule = (SendMessage(GetDlgItem(hwndDlg, IDC_CHK_LOGMODULE), BM_GETCHECK, 0,0) == BST_CHECKED);
  214. if (settings.logPath) free(settings.logPath);
  215. settings.logPath = NULL;
  216. len = GetWindowText(GetDlgItem(hwndDlg, IDC_EDT_LOGNAME), buf, 1024);
  217. if (len)
  218. {
  219. if (pathlen)
  220. {
  221. len += pathlen;
  222. settings.logPath = (wchar_t*)malloc((len + 1)*2);
  223. StringCchPrintf(settings.logPath, len+1, L"%s\\%s", path, buf);
  224. }
  225. else
  226. {
  227. settings.logPath = (wchar_t*)malloc((len + 1)*2);
  228. StringCchCopy(settings.logPath, len+1, buf);
  229. }
  230. }
  231. if (!settings.Save())
  232. {
  233. wchar_t title[32] = {0};
  234. MessageBox(NULL, WASABI_API_LNGSTRINGW(IDS_UNABLE_TO_SAVE_SETTINGS),
  235. WASABI_API_LNGSTRINGW_BUF(IDS_SAVE_ERROR,title,32), MB_OK);
  236. }
  237. if(path) free(path);
  238. path = NULL;
  239. break;
  240. }
  241. case WM_COMMAND:
  242. int ctrl = LOWORD(wParam);
  243. switch (ctrl)
  244. {
  245. case IDC_CHK_CREATELOG:
  246. case IDC_CHK_CREATEDMP:
  247. case IDC_CHK_SEND:
  248. case IDC_CHK_COMPRESS:
  249. if (HIWORD(wParam) == BN_CLICKED)
  250. {
  251. BOOL enabled = (SendMessage((HWND) lParam, BM_GETCHECK, 0,0) == BST_CHECKED);
  252. if (ctrl == IDC_CHK_CREATELOG) UpdateCreateLog(hwndDlg, enabled);
  253. else if (ctrl == IDC_CHK_CREATEDMP) UpdateCreateDmp(hwndDlg, enabled);
  254. else if (ctrl == IDC_CHK_SEND) UpdateSend(hwndDlg, enabled);
  255. else if (ctrl == IDC_CHK_COMPRESS) UpdateZip(hwndDlg, enabled);
  256. }
  257. break;
  258. case IDC_RB_USESMTP:
  259. case IDC_RB_USECLIENT:
  260. if (HIWORD(wParam) == BN_CLICKED) UpdateSendType(hwndDlg, (ctrl == IDC_RB_USESMTP));
  261. break;
  262. case IDC_BTN_PATH:
  263. {
  264. wchar_t szFile[2048] = {0}; // buffer for file name
  265. GetWindowText(GetDlgItem(hwndDlg, IDC_EDT_PATH), szFile, 2048);
  266. if (OpenFolderDialog(NULL, szFile))SetWindowText(GetDlgItem(hwndDlg, IDC_EDT_PATH), szFile);
  267. }
  268. break;
  269. case IDC_BTN_SMTP:
  270. WASABI_API_DIALOGBOXW(IDD_DLG_SMTP, hwndDlg, (DLGPROC)smtpDlgProc);
  271. break;
  272. }
  273. break;
  274. }
  275. //settings.smtpUser;
  276. return FALSE;
  277. }
  278. int SelectComboBoxItem(const HWND hwCombo, int data)
  279. {
  280. int count = (int) SendMessage(hwCombo, CB_GETCOUNT , 0, 0);
  281. for (int i = 0; i < count; i++)
  282. {
  283. if (data == (int) SendMessage(hwCombo, CB_GETITEMDATA, i, 0))
  284. return (int) SendMessage(hwCombo, CB_SETCURSEL, i, 0);
  285. }
  286. return -1;
  287. }
  288. void UpdateZip(HWND hwndDlg, BOOL enabled)
  289. {
  290. EnableWindow(GetDlgItem(hwndDlg, IDC_GRP_ZIP), enabled);
  291. EnableWindow(GetDlgItem(hwndDlg, IDC_LBL_ZIPNAME), enabled);
  292. EnableWindow(GetDlgItem(hwndDlg, IDC_EDT_ZIPNAME), enabled);
  293. }
  294. void UpdateSendType(HWND hwndDlg, BOOL enabled)
  295. {
  296. EnableWindow(GetDlgItem(hwndDlg, IDC_BTN_SMTP), enabled);
  297. }
  298. void UpdateSend(HWND hwndDlg, BOOL enabled)
  299. {
  300. EnableWindow(GetDlgItem(hwndDlg, IDC_RB_USECLIENT), enabled);
  301. EnableWindow(GetDlgItem(hwndDlg, IDC_RB_USESMTP), enabled);
  302. BOOL stmpPressed = (SendMessage(GetDlgItem(hwndDlg,IDC_RB_USESMTP), BM_GETCHECK, 0,0) == BST_CHECKED);
  303. EnableWindow(GetDlgItem(hwndDlg, IDC_BTN_SMTP), enabled && stmpPressed);
  304. }
  305. void UpdateCreateDmp(HWND hwndDlg, BOOL enabled)
  306. {
  307. EnableWindow(GetDlgItem(hwndDlg, IDC_LBL_OSVERSION_CAPTION), enabled);
  308. EnableWindow(GetDlgItem(hwndDlg, IDC_LBL_DLLPATH_CAPTION), enabled);
  309. EnableWindow(GetDlgItem(hwndDlg, IDC_LBL_DLLVERSION_CAPTION), enabled);
  310. EnableWindow(GetDlgItem(hwndDlg, IDC_LBL_OSVERSION), enabled);
  311. EnableWindow(GetDlgItem(hwndDlg, IDC_LBL_DLLPATH), enabled);
  312. EnableWindow(GetDlgItem(hwndDlg, IDC_LBL_DLLVERSION), enabled);
  313. EnableWindow(GetDlgItem(hwndDlg, IDC_LBL_DMPTYPE), enabled);
  314. EnableWindow(GetDlgItem(hwndDlg, IDC_CMB_DMPTYPE), enabled);
  315. EnableWindow(GetDlgItem(hwndDlg, IDC_LBL_DMPNAME), enabled);
  316. EnableWindow(GetDlgItem(hwndDlg, IDC_EDT_DMPNAME), enabled);
  317. }
  318. void UpdateCreateLog(HWND hwndDlg, BOOL enabled)
  319. {
  320. EnableWindow(GetDlgItem(hwndDlg, IDC_GRP_LOG), enabled);
  321. EnableWindow(GetDlgItem(hwndDlg, IDC_CHK_LOGSYSTEM), enabled);
  322. EnableWindow(GetDlgItem(hwndDlg, IDC_CHK_LOGREGISTRY), enabled);
  323. EnableWindow(GetDlgItem(hwndDlg, IDC_CHK_LOGSTACK), enabled);
  324. EnableWindow(GetDlgItem(hwndDlg, IDC_CHK_LOGMODULE), enabled);
  325. EnableWindow(GetDlgItem(hwndDlg, IDC_LBL_LOGNAME), enabled);
  326. EnableWindow(GetDlgItem(hwndDlg, IDC_EDT_LOGNAME), enabled);
  327. }
  328. BOOL CALLBACK browseEnumProc(HWND hwnd, LPARAM lParam)
  329. {
  330. wchar_t cl[32] = {0};
  331. GetClassNameW(hwnd, cl, ARRAYSIZE(cl));
  332. if (!lstrcmpiW(cl, WC_TREEVIEW))
  333. {
  334. PostMessage(hwnd, TVM_ENSUREVISIBLE, 0, (LPARAM)TreeView_GetSelection(hwnd));
  335. return FALSE;
  336. }
  337. return TRUE;
  338. }
  339. static int CALLBACK WINAPI BrowseCallbackProc( HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
  340. {
  341. switch (uMsg)
  342. {
  343. case BFFM_INITIALIZED:
  344. {
  345. //SetWindowText(hwnd, getString(IDS_P_SELECT_LANGDIR,NULL,0));
  346. SendMessage(hwnd, BFFM_SETSELECTION, 1, (LPARAM)lpData);
  347. // this is not nice but it fixes the selection not working correctly on all OSes
  348. EnumChildWindows(hwnd, browseEnumProc, 0);
  349. }
  350. return 0;
  351. }
  352. return 0;
  353. }
  354. BOOL OpenFolderDialog(HWND parent, LPWSTR pathBuffer)
  355. {
  356. if (!pathBuffer) return FALSE;
  357. // Return value for the function
  358. BOOL ret = TRUE;
  359. // Set up the params
  360. BROWSEINFO browseInfo = {0};
  361. browseInfo.hwndOwner = parent;
  362. browseInfo.lpfn = BrowseCallbackProc;
  363. browseInfo.lParam = (LPARAM)pathBuffer;
  364. browseInfo.lpszTitle = WASABI_API_LNGSTRINGW(IDS_SELECT_FOLDER_FOR_ERROR_INFO);
  365. browseInfo.ulFlags = BIF_NEWDIALOGSTYLE;
  366. // Show the dialog
  367. LPITEMIDLIST itemIDList = SHBrowseForFolder(&browseInfo);
  368. // Did user press cancel?
  369. if (!itemIDList)
  370. ret = FALSE;
  371. // Is everything so far?
  372. if (ret != FALSE)
  373. {
  374. // Get the path from the returned ITEMIDLIST
  375. if (!SHGetPathFromIDList(itemIDList, pathBuffer))
  376. ret = FALSE;
  377. // Now we need to free the ITEMIDLIST the shell allocated
  378. LPMALLOC shellMalloc;
  379. HRESULT hr;
  380. // Get pointer to the shell's malloc interface
  381. hr = SHGetMalloc(&shellMalloc);
  382. // Did it work?
  383. if (SUCCEEDED(hr))
  384. {
  385. shellMalloc->Free(itemIDList);
  386. shellMalloc->Release();
  387. ret = TRUE;
  388. }
  389. }
  390. return ret;
  391. }
  392. void CreatePathFromFullName(wchar_t **path, const wchar_t *fullname)
  393. {
  394. if (*path) free(*path);
  395. *path = NULL;
  396. if (!fullname) return;
  397. const wchar_t *end = wcsrchr(fullname, L'\\');
  398. if (!end || end == fullname) return;
  399. int len = (int)(end - fullname + 1);
  400. if (len == 3) len++;
  401. *path = (wchar_t*)malloc(len*2);
  402. StringCchCopyN(*path, len, fullname, len -1);
  403. }
  404. const wchar_t* GetFileName(const wchar_t *fullname)
  405. {
  406. if (!fullname) return NULL;
  407. const wchar_t *start = wcsrchr(fullname, L'\\');
  408. if (start && start != fullname) start = CharNext(start);
  409. return start;
  410. }