Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

453 lines
13 KiB

  1. #define UNICODE 1
  2. #include "shellprv.h"
  3. #pragma hdrstop
  4. const WCHAR szCommdlgHelp[] = L"commdlg_help";
  5. UINT wBrowseHelp = WM_USER; /* Set to an unused value */
  6. const CHAR szGetOpenFileName[] = "GetOpenFileNameW";
  7. /* the defines below should be in windows.h */
  8. /* Dialog window class */
  9. #define WC_DIALOG (MAKEINTATOM(0x8002))
  10. /* cbWndExtra bytes needed by dialog manager for dialog classes */
  11. #define DLGWINDOWEXTRA 30
  12. /* Get/SetWindowWord/Long offsets for use with WC_DIALOG windows */
  13. #define DWL_MSGRESULT 0
  14. #define DWL_DLGPROC 4
  15. #define DWL_USER 8
  16. /* For Long File Name support */
  17. #define MAX_EXTENSION 64
  18. typedef struct {
  19. LPWSTR lpszExe;
  20. LPWSTR lpszPath;
  21. LPWSTR lpszName;
  22. } FINDEXE_PARAMS, FAR *LPFINDEXE_PARAMS;
  23. typedef INT (APIENTRY *LPFNGETOPENFILENAME)(LPOPENFILENAME);
  24. VOID APIENTRY
  25. CheckEscapesW(LPWSTR szFile, DWORD cch)
  26. {
  27. LPWSTR szT;
  28. WCHAR *p, *pT;
  29. for (p = szFile; *p; p++) {
  30. switch (*p) {
  31. case WCHAR_SPACE:
  32. case WCHAR_COMMA:
  33. case WCHAR_SEMICOLON:
  34. case WCHAR_HAT:
  35. case WCHAR_QUOTE:
  36. {
  37. // this path contains an annoying character
  38. if (cch < (wcslen(szFile) + 2)) {
  39. return;
  40. }
  41. szT = (LPWSTR)LocalAlloc(LPTR, cch * sizeof(WCHAR));
  42. if (!szT) {
  43. return;
  44. }
  45. wcscpy(szT,szFile);
  46. p = szFile;
  47. *p++ = WCHAR_QUOTE;
  48. for (pT = szT; *pT; ) {
  49. *p++ = *pT++;
  50. }
  51. *p++ = WCHAR_QUOTE;
  52. *p = WCHAR_NULL;
  53. LocalFree(szT);
  54. return;
  55. }
  56. }
  57. }
  58. }
  59. VOID APIENTRY
  60. CheckEscapesA(LPSTR lpFileA, DWORD cch)
  61. {
  62. if (lpFileA && *lpFileA) {
  63. LPWSTR lpFileW;
  64. lpFileW = (LPWSTR)LocalAlloc(LPTR, (cch * sizeof(WCHAR)));
  65. if (!lpFileW) {
  66. return;
  67. }
  68. SHAnsiToUnicode(lpFileA, lpFileW, cch);
  69. CheckEscapesW(lpFileW, cch);
  70. try {
  71. SHUnicodeToAnsi(lpFileW, lpFileA, cch);
  72. } except(EXCEPTION_EXECUTE_HANDLER) {
  73. LocalFree(lpFileW);
  74. return;
  75. }
  76. LocalFree(lpFileW);
  77. }
  78. return;
  79. }
  80. // Hooks into common dialog to allow size of selected files to be displayed.
  81. BOOL APIENTRY
  82. LocateHookProc(
  83. HWND hDlg,
  84. UINT uiMessage,
  85. WPARAM wParam,
  86. LONG lParam)
  87. {
  88. WCHAR szTemp[40];
  89. WORD wID;
  90. switch (uiMessage) {
  91. case WM_INITDIALOG:
  92. PostMessage(hDlg, WM_COMMAND, ctlLast+1, 0L);
  93. break;
  94. case WM_COMMAND:
  95. switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  96. case ctlLast+1:
  97. GetDlgItemText(hDlg, edt1, szTemp, ARRAYSIZE(szTemp));
  98. if (SendDlgItemMessage(hDlg, lst1, LB_FINDSTRING, (WPARAM)-1,
  99. (LONG_PTR)(LPSTR)szTemp) >= 0) {
  100. wID = IDS_PROGFOUND;
  101. } else {
  102. wID = IDS_PROGNOTFOUND;
  103. }
  104. LoadString(HINST_THISDLL, wID, szTemp, ARRAYSIZE(szTemp));
  105. SetDlgItemText(hDlg, ctlLast+2, szTemp);
  106. break;
  107. case lst2:
  108. if (GET_WM_COMMAND_CMD(wParam, lParam) == LBN_DBLCLK)
  109. PostMessage(hDlg, WM_COMMAND, ctlLast+1, 0L);
  110. break;
  111. case cmb2:
  112. switch (GET_WM_COMMAND_CMD(wParam, lParam)) {
  113. case CBN_SELCHANGE:
  114. PostMessage(hDlg, WM_COMMAND, ctlLast+1, 1L);
  115. break;
  116. case CBN_CLOSEUP:
  117. PostMessage(hDlg, WM_COMMAND, GET_WM_COMMAND_MPS(cmb2,
  118. GetDlgItem(hDlg, cmb2), CBN_SELCHANGE));
  119. break;
  120. }
  121. break;
  122. case IDOK:
  123. case IDCANCEL:
  124. case IDABORT:
  125. PostMessage(hDlg, WM_COMMAND, ctlLast+1, 0L);
  126. break;
  127. }
  128. break;
  129. }
  130. UNREFERENCED_PARAMETER(lParam);
  131. return(FALSE); // commdlg, do your thing
  132. }
  133. BOOL_PTR APIENTRY
  134. FindExeDlgProcW(
  135. HWND hDlg,
  136. register UINT wMsg,
  137. WPARAM wParam,
  138. LPARAM lParam)
  139. {
  140. /* Notice this is OK as a global, because it will be reloaded
  141. * when needed
  142. */
  143. static HANDLE hCommDlg = NULL;
  144. WCHAR szPath[MAX_PATH]; /* This must be the same size as lpfind->lpszPath */
  145. WCHAR szBuffer[MAX_PATH + 100];
  146. LPFINDEXE_PARAMS lpfind;
  147. int temp;
  148. LPWSTR lpTemp;
  149. switch (wMsg) {
  150. case WM_INITDIALOG:
  151. wBrowseHelp = RegisterWindowMessage(szCommdlgHelp);
  152. lpfind = (LPFINDEXE_PARAMS)lParam;
  153. SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)lpfind);
  154. GetDlgItemText(hDlg, IDD_TEXT1, szPath, ARRAYSIZE(szPath));
  155. wsprintf(szBuffer, szPath, lpfind->lpszExe, lpfind->lpszName);
  156. SetDlgItemText(hDlg, IDD_TEXT1, szBuffer);
  157. GetDlgItemText(hDlg, IDD_TEXT2, szPath, ARRAYSIZE(szPath));
  158. wsprintf(szBuffer, szPath, lpfind->lpszExe);
  159. SetDlgItemText(hDlg, IDD_TEXT2, szBuffer);
  160. SetDlgItemText(hDlg, IDD_PATH, lpfind->lpszPath);
  161. break;
  162. case WM_DESTROY:
  163. if (hCommDlg >= (HANDLE)32) {
  164. FreeLibrary(hCommDlg);
  165. hCommDlg = NULL;
  166. }
  167. break;
  168. case WM_COMMAND:
  169. switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  170. case IDD_BROWSE:
  171. {
  172. LPFNGETOPENFILENAME lpfnGetOpenFileName;
  173. WCHAR szExts[MAX_EXTENSION];
  174. OPENFILENAME ofn;
  175. GetDlgItemText(hDlg, IDD_PATH, szBuffer, ARRAYSIZE(szBuffer));
  176. lpfind = (LPFINDEXE_PARAMS)GetWindowLongPtr(hDlg, DWLP_USER);
  177. wcscpy(szPath, lpfind->lpszExe);
  178. SheRemoveQuotesW(szPath);
  179. /* Make up a file types string
  180. */
  181. // BUG BUG this assumes extensions are of length 3.
  182. szExts[0] = WCHAR_CAP_A;
  183. szExts[1] = WCHAR_NULL;
  184. szExts[2] = WCHAR_STAR;
  185. szExts[3] = WCHAR_DOT;
  186. szExts[4] = WCHAR_NULL;
  187. if (NULL != (lpTemp=StrRChrW(szPath, NULL, WCHAR_DOT)))
  188. StrCpyN(szExts+3, lpTemp, ((wcslen(lpTemp) < 60) ? wcslen(lpTemp) : 60));
  189. szExts[3+wcslen(szExts+3)+1] = WCHAR_NULL;
  190. ofn.lStructSize = sizeof(OPENFILENAME);
  191. ofn.hwndOwner = hDlg;
  192. ofn.hInstance = HINST_THISDLL;
  193. ofn.lpstrFilter = L"A\0\?.?\0"; // a dummy filter
  194. ofn.lpstrCustomFilter = NULL;
  195. ofn.nMaxCustFilter = 0;
  196. ofn.nFilterIndex = 1;
  197. ofn.lpstrFile = szPath;
  198. ofn.nMaxFile = sizeof(szPath);
  199. ofn.lpstrInitialDir = NULL;
  200. ofn.lpstrTitle = NULL;
  201. ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST |
  202. OFN_ENABLETEMPLATE | OFN_SHOWHELP;
  203. ofn.lCustData = (LONG_PTR) hDlg;
  204. ofn.lpfnHook = NULL; // AddFileHookProc;
  205. ofn.lpTemplateName = MAKEINTRESOURCE(DLG_BROWSE);
  206. ofn.nFileOffset = 0;
  207. ofn.nFileExtension = 0;
  208. ofn.lpstrDefExt = NULL;
  209. ofn.lpstrFileTitle = NULL;
  210. if (hCommDlg < (HANDLE)32 &&
  211. (hCommDlg = LoadLibrary(TEXT("comdlg32.dll"))) < (HANDLE)32) {
  212. CommDlgError:
  213. LoadString(HINST_THISDLL, IDS_NOCOMMDLG, szBuffer, ARRAYSIZE(szBuffer));
  214. GetWindowText(hDlg, szPath, ARRAYSIZE(szPath));
  215. MessageBox(hDlg, szBuffer, szPath, MB_ICONHAND|MB_OK);
  216. break;
  217. }
  218. if (!(lpfnGetOpenFileName =
  219. (LPFNGETOPENFILENAME)GetProcAddress((HINSTANCE)hCommDlg,
  220. (LPSTR)szGetOpenFileName)))
  221. goto CommDlgError;
  222. temp = (*lpfnGetOpenFileName)(&ofn);
  223. if (temp) {
  224. LPWSTR lpTemp;
  225. lpTemp = StrRChrW(szPath, NULL, WCHAR_BSLASH);
  226. *lpTemp = WCHAR_NULL;
  227. SetDlgItemText(hDlg, IDD_PATH, szPath);
  228. }
  229. break;
  230. }
  231. case IDOK:
  232. {
  233. HANDLE hFile;
  234. lpfind = (LPFINDEXE_PARAMS)GetWindowLongPtr(hDlg, DWLP_USER);
  235. if (lpfind) {
  236. GetDlgItemText(hDlg, IDD_PATH, lpfind->lpszPath, MAX_PATH);
  237. switch (*CharPrev(lpfind->lpszPath,
  238. lpTemp=lpfind->lpszPath+lstrlen(lpfind->lpszPath))) {
  239. case WCHAR_BSLASH:
  240. case WCHAR_COLON:
  241. break;
  242. default:
  243. *lpTemp++ = WCHAR_BSLASH;
  244. break;
  245. }
  246. wcscpy(lpTemp, lpfind->lpszExe);
  247. hFile = CreateFile(lpfind->lpszPath, GENERIC_EXECUTE, (FILE_SHARE_READ | FILE_SHARE_WRITE),
  248. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  249. if (hFile == INVALID_HANDLE_VALUE) {
  250. LoadString(HINST_THISDLL, IDS_STILLNOTFOUND, szPath, ARRAYSIZE(szPath));
  251. wsprintf(szBuffer, szPath, lpfind->lpszPath);
  252. GetWindowText(hDlg, szPath, ARRAYSIZE(szPath));
  253. MessageBox(hDlg, szBuffer, szPath, MB_ICONHAND|MB_OK);
  254. break;
  255. }
  256. WriteProfileString(TEXT("programs"), lpfind->lpszExe,
  257. lpfind->lpszPath);
  258. }
  259. }
  260. // fall through
  261. case IDCANCEL:
  262. EndDialog(hDlg, GET_WM_COMMAND_ID(wParam, lParam) == IDOK);
  263. break;
  264. }
  265. break;
  266. default:
  267. return FALSE;
  268. }
  269. return TRUE;
  270. }
  271. // Returns -1 if we found the file (and it was not in an obvious place)
  272. // or an error code which will be returned to the app (see the error
  273. // returns for ShellExecute)
  274. HANDLE APIENTRY
  275. FindAssociatedExeW(
  276. HWND hwnd,
  277. LPWSTR lpCommand,
  278. LPWSTR lpName)
  279. {
  280. FINDEXE_PARAMS find;
  281. WCHAR szPath[MAX_PATH];
  282. WCHAR szExe[MAX_PATH];
  283. LPWSTR lpSpace, lpTemp;
  284. HANDLE hFile = NULL;
  285. BOOL fQuote = FALSE;
  286. // find the param list
  287. lpSpace = lpCommand;
  288. while (*lpSpace)
  289. {
  290. if ((*lpSpace == WCHAR_SPACE) && (!fQuote))
  291. {
  292. break;
  293. }
  294. else if (*lpSpace == WCHAR_QUOTE)
  295. {
  296. fQuote = !fQuote;
  297. }
  298. lpSpace++;
  299. }
  300. if (*lpSpace == WCHAR_SPACE) {
  301. *lpSpace = 0;
  302. wcscpy(szPath, lpCommand);
  303. *lpSpace = WCHAR_SPACE;
  304. } else {
  305. lpSpace = TEXT("");
  306. wcscpy(szPath, lpCommand);
  307. }
  308. SheRemoveQuotesW(szPath);
  309. /* Add ".exe" if there is no extension
  310. * Check if the file can be opened; if it can, then some DLL could not
  311. * be found during the WinExec, so return file not found
  312. */
  313. if (NULL != (lpTemp=StrRChrW(szPath, NULL, WCHAR_BSLASH))
  314. || NULL != (lpTemp=StrRChrW(szPath, NULL, WCHAR_COLON))) {
  315. ++lpTemp;
  316. } else {
  317. lpTemp = szPath;
  318. }
  319. hFile = CreateFile(szPath, GENERIC_EXECUTE, (FILE_SHARE_READ | FILE_SHARE_WRITE),
  320. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  321. if (hFile != INVALID_HANDLE_VALUE) {
  322. CloseHandle(hFile);
  323. return((HANDLE)2);
  324. }
  325. // store the file name component
  326. wcscpy(szExe, lpTemp);
  327. // make sure there is an extension
  328. if (!StrChrW(szExe, WCHAR_DOT)) {
  329. wcscat(szExe, TEXT(".exe"));
  330. }
  331. // add back the quotes, if necessary
  332. CheckEscapesW(szExe, MAX_PATH);
  333. // look in win.ini
  334. GetProfileString(TEXT("programs"), szExe, TEXT(""), szPath, ARRAYSIZE(szPath));
  335. if (szPath[0]) {
  336. hFile = CreateFile(szPath, GENERIC_EXECUTE, (FILE_SHARE_READ | FILE_SHARE_WRITE),
  337. NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  338. if (hFile != INVALID_HANDLE_VALUE) {
  339. CloseHandle(hFile);
  340. wcscat(szPath, lpSpace); // add the parameters
  341. wcscpy(lpCommand, szPath); // return the new path
  342. return((HANDLE)-1);
  343. }
  344. /* Strip off the file part */
  345. if (NULL != (lpTemp=StrRChrW(szPath, NULL, WCHAR_BSLASH))) {
  346. if (*CharPrev(szPath, lpTemp) == WCHAR_COLON) {
  347. ++lpTemp;
  348. }
  349. *lpTemp = WCHAR_NULL;
  350. } else if (NULL != (lpTemp=StrRChrW(szPath, NULL, WCHAR_COLON))) {
  351. *(lpTemp+1) = WCHAR_NULL;
  352. }
  353. } else {
  354. /* Prompt with the disk that Windows is on */
  355. GetWindowsDirectory(szPath, ARRAYSIZE(szPath)-1);
  356. szPath[3] = WCHAR_NULL;
  357. }
  358. find.lpszExe = szExe;
  359. find.lpszPath = szPath;
  360. find.lpszName = lpName;
  361. switch(DialogBoxParam(HINST_THISDLL, MAKEINTRESOURCE(DLG_FINDEXE), hwnd,
  362. FindExeDlgProcW, (LONG_PTR)(LPFINDEXE_PARAMS)&find)) {
  363. case IDOK:
  364. wcscat(szPath, lpSpace); // add the parameters
  365. wcscpy(lpCommand, szPath); // return the new path
  366. return ((HANDLE)-1);
  367. case IDCANCEL:
  368. return((HANDLE)15); // This is the user cancel return
  369. default:
  370. return((HANDLE)2); // stick with the file not found
  371. }
  372. }