Leaked source code of windows server 2003
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.

468 lines
11 KiB

  1. // SelectFile.cpp : Implementation of CSelectFile
  2. #include "stdafx.h"
  3. #include "CompatUI.h"
  4. #include "SelectFile.h"
  5. #include "commdlg.h"
  6. #include "cderr.h"
  7. /////////////////////////////////////////////////////////////////////////////
  8. // CSelectFile
  9. //
  10. // in upload.c
  11. //
  12. wstring StrUpCase(wstring& wstr);
  13. STDMETHODIMP CSelectFile::get_BrowseTitle(BSTR *pVal)
  14. {
  15. *pVal = m_bstrTitle.Copy();
  16. return S_OK;
  17. }
  18. STDMETHODIMP CSelectFile::put_BrowseTitle(BSTR newVal)
  19. {
  20. m_bstrTitle = newVal;
  21. return S_OK;
  22. }
  23. STDMETHODIMP CSelectFile::get_BrowseFilter(BSTR *pVal)
  24. {
  25. *pVal = m_bstrFilter.Copy();
  26. return S_OK;
  27. }
  28. STDMETHODIMP CSelectFile::put_BrowseFilter(BSTR newVal)
  29. {
  30. m_bstrFilter = newVal;
  31. return S_OK;
  32. }
  33. STDMETHODIMP CSelectFile::get_BrowseInitialDirectory(BSTR *pVal)
  34. {
  35. *pVal = m_bstrInitialDirectory;
  36. return S_OK;
  37. }
  38. STDMETHODIMP CSelectFile::put_BrowseInitialDirectory(BSTR newVal)
  39. {
  40. m_bstrInitialDirectory = newVal;
  41. return S_OK;
  42. }
  43. STDMETHODIMP CSelectFile::get_BrowseFlags(long *pVal)
  44. {
  45. *pVal = (LONG)m_dwBrowseFlags;
  46. return S_OK;
  47. }
  48. STDMETHODIMP CSelectFile::put_BrowseFlags(long newVal)
  49. {
  50. m_dwBrowseFlags = (DWORD)newVal;
  51. return S_OK;
  52. }
  53. STDMETHODIMP CSelectFile::get_FileName(BSTR *pVal)
  54. {
  55. wstring sFileName;
  56. if (!m_Safe) {
  57. return HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED);
  58. }
  59. GetFileNameFromUI(sFileName);
  60. m_bstrFileName = sFileName.c_str();
  61. *pVal = m_bstrFileName.Copy();
  62. return S_OK;
  63. }
  64. STDMETHODIMP CSelectFile::put_FileName(BSTR newVal)
  65. {
  66. m_bstrFileName = newVal;
  67. SetDlgItemText(IDC_EDITFILENAME, m_bstrFileName);
  68. return S_OK;
  69. }
  70. STDMETHODIMP CSelectFile::get_ErrorCode(long *pVal)
  71. {
  72. *pVal = (LONG)m_dwErrorCode;
  73. return S_OK;
  74. }
  75. #define MAX_BUFFER 2048
  76. LRESULT CSelectFile::OnClickedBrowse(
  77. WORD wNotifyCode,
  78. WORD wID,
  79. HWND hWndCtl,
  80. BOOL& bHandled)
  81. {
  82. LRESULT lRes = 0;
  83. // TODO: Add your implementation code here
  84. OPENFILENAME ofn;
  85. LPTSTR pszFileName = NULL;
  86. DWORD dwFileNameLength = 0;
  87. DWORD dwLen;
  88. LPTSTR pszFilter = NULL, pch;
  89. m_dwErrorCode = 0;
  90. ZeroMemory(&ofn, sizeof(ofn));
  91. ofn.lStructSize = sizeof(ofn);
  92. ofn.hwndOwner = m_hWnd;
  93. //
  94. // part one (straight) - title
  95. //
  96. ofn.lpstrTitle = (LPCTSTR)m_bstrTitle; // assumes we're unicode (and we are)
  97. //
  98. // recover the filename from the edit box
  99. //
  100. wstring sFileName;
  101. if (GetFileNameFromUI(sFileName)) {
  102. m_bstrFileName = sFileName.c_str();
  103. }
  104. //
  105. // part two - init filename
  106. //
  107. dwFileNameLength = __max(MAX_BUFFER, m_bstrFileName.Length() * 2); // in characters
  108. pszFileName = new TCHAR[dwFileNameLength * sizeof(*pszFileName)];
  109. if (pszFileName == NULL) {
  110. m_dwErrorCode = ERROR_OUTOFMEMORY;
  111. goto HandleError;
  112. }
  113. // so we have the buffer now
  114. //
  115. if (m_bstrFileName.Length () > 0) {
  116. // sanitize the filename with regard to quotes
  117. _tcscpy(pszFileName, (LPCTSTR)m_bstrFileName); // hypocritical copy, we are unicode
  118. } else {
  119. // start with the contents of the text box then
  120. *pszFileName = TEXT('\0');
  121. }
  122. //
  123. // sanity check, if pszFileName ends with \ then we will get an error
  124. //
  125. PathRemoveBackslash(pszFileName);
  126. ofn.lpstrFile = pszFileName;
  127. ofn.nMaxFile = dwFileNameLength;
  128. //
  129. // see if we also need to process filter
  130. //
  131. if (m_bstrFilter.Length() > 0) {
  132. dwLen = m_bstrFilter.Length();
  133. pszFilter = new TCHAR[(dwLen + 2) * sizeof(*pszFilter)];
  134. if (pszFilter == NULL) {
  135. m_dwErrorCode = ERROR_OUTOFMEMORY;
  136. goto HandleError;
  137. }
  138. RtlZeroMemory(pszFilter, (dwLen + 2) * sizeof(*pszFilter));
  139. _tcscpy(pszFilter, m_bstrFilter);
  140. pch = pszFilter;
  141. while (pch) {
  142. pch = _tcschr(pch, TEXT('|'));
  143. if (pch) {
  144. *pch++ = TEXT('\0');
  145. }
  146. }
  147. // now that the replacement is done -- assign the filter string
  148. ofn.lpstrFilter = pszFilter;
  149. }
  150. //
  151. // now check whether we have some in the initial directory
  152. //
  153. if (m_bstrInitialDirectory.Length() > 0) {
  154. ofn.lpstrInitialDir = (LPCTSTR)m_bstrInitialDirectory;
  155. }
  156. //
  157. // flags
  158. //
  159. if (m_dwBrowseFlags) {
  160. ofn.Flags = m_dwBrowseFlags;
  161. } else {
  162. ofn.Flags = OFN_FILEMUSTEXIST|OFN_EXPLORER;
  163. }
  164. BOOL bRetry;
  165. BOOL bSuccess;
  166. do {
  167. bRetry = FALSE;
  168. bSuccess = GetOpenFileName(&ofn);
  169. if (!bSuccess) {
  170. m_dwErrorCode = CommDlgExtendedError();
  171. if (m_dwErrorCode == FNERR_INVALIDFILENAME) {
  172. *pszFileName = TEXT('\0');
  173. bRetry = TRUE;
  174. }
  175. }
  176. } while (bRetry);
  177. if (!bSuccess) {
  178. goto HandleError;
  179. }
  180. SetDlgItemText(IDC_EDITFILENAME, pszFileName);
  181. m_bstrFileName = (LPCTSTR)pszFileName;
  182. m_dwErrorCode = 0;
  183. HandleError:
  184. if (pszFileName != NULL) {
  185. delete[] pszFileName;
  186. }
  187. if (pszFilter != NULL) {
  188. delete[] pszFilter;
  189. }
  190. bHandled = TRUE;
  191. return lRes;
  192. }
  193. BOOL
  194. CSelectFile::PreTranslateAccelerator(
  195. LPMSG pMsg,
  196. HRESULT& hRet
  197. )
  198. {
  199. HWND hWndCtl;
  200. HWND hwndEdit = GetDlgItem(IDC_EDITFILENAME);
  201. HWND hwndBrowse = GetDlgItem(IDC_BROWSE);
  202. BSTR bstrFileName = NULL;
  203. WORD wCmd = 0;
  204. BOOL bBrowseHandled;
  205. hRet = S_OK;
  206. hWndCtl = ::GetFocus();
  207. if (IsChild(hWndCtl) && ::GetParent(hWndCtl) != m_hWnd) {
  208. do {
  209. hWndCtl = ::GetParent(hWndCtl);
  210. } while (::GetParent(hWndCtl) != m_hWnd);
  211. }
  212. if (pMsg->message == WM_KEYDOWN &&
  213. (LOWORD(pMsg->wParam) == VK_RETURN ||
  214. LOWORD(pMsg->wParam) == VK_EXECUTE)) {
  215. if (hWndCtl == hwndEdit) {
  216. BOOL bReturn;
  217. wstring sFileName;
  218. bReturn = GetFileNameFromUI(sFileName) &&
  219. ValidateExecutableFile(sFileName.c_str(), TRUE);
  220. if (bReturn) {
  221. Fire_SelectionComplete();
  222. return TRUE;
  223. }
  224. }
  225. // this either was hwndBrowse or filename was not there -- open
  226. // browse dialog then
  227. OnClickedBrowse(BN_CLICKED, IDC_BROWSE, hwndBrowse, bBrowseHandled);
  228. ::SetFocus(hwndEdit);
  229. }
  230. //
  231. // fixup external accelerators for internal controls (in this case -- edit)
  232. //
  233. if (m_Accel.IsAccelKey(pMsg, &wCmd) && wCmd == IDC_EDITFILENAME) {
  234. ::SetFocus(hwndEdit);
  235. return TRUE;
  236. }
  237. //
  238. // check for external accelerators because the next call is going to eat the message
  239. //
  240. if (m_ExternAccel.IsAccelKey(pMsg)) { // we do not touch external accel messages
  241. return FALSE;
  242. }
  243. //
  244. // check whether we are tabbing out of control
  245. //
  246. if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_TAB) {
  247. // check whether we're tabbing out
  248. // (perhaps the control wants to eat tab?
  249. DWORD_PTR dwDlgCode = ::SendMessage(pMsg->hwnd, WM_GETDLGCODE, 0, 0);
  250. if (!(dwDlgCode & DLGC_WANTTAB)) {
  251. // control does not want a tab
  252. // see whether it's the last control and we're tabbing out
  253. HWND hwndFirst = GetNextDlgTabItem(NULL, FALSE); // first
  254. HWND hwndLast = GetNextDlgTabItem(hwndFirst, TRUE);
  255. BOOL bFirstOrLast;
  256. if (::GetKeyState(VK_SHIFT) & 0x8000) {
  257. // shift ?
  258. bFirstOrLast = (hWndCtl == hwndFirst);
  259. } else {
  260. bFirstOrLast = (hWndCtl == hwndLast);
  261. }
  262. if (bFirstOrLast) {
  263. IsDialogMessage(pMsg);
  264. return FALSE;
  265. }
  266. }
  267. }
  268. return CComCompositeControl<CSelectFile>::PreTranslateAccelerator(pMsg, hRet);
  269. }
  270. /*
  271. STDMETHODIMP CSelectFile::get_Accel(BSTR *pVal)
  272. {
  273. CComBSTR bstr = (LPCWSTR)m_Accel;
  274. *pVal = bstr.Copy();
  275. return S_OK;
  276. }
  277. STDMETHODIMP CSelectFile::put_Accel(BSTR newVal)
  278. {
  279. m_Accel = (LPCWSTR)newVal;
  280. return S_OK;
  281. }
  282. */
  283. STDMETHODIMP CSelectFile::get_ExternAccel(BSTR *pVal)
  284. {
  285. CComBSTR bstr = m_ExternAccel.GetAccelString(0).c_str();
  286. *pVal = bstr.Copy();
  287. return S_OK;
  288. }
  289. STDMETHODIMP CSelectFile::put_ExternAccel(BSTR newVal)
  290. {
  291. m_ExternAccel = (LPCWSTR)newVal;
  292. return S_OK;
  293. }
  294. static TCHAR szU[] = TEXT("<U>");
  295. static TCHAR szUC[] = TEXT("</U>");
  296. #define szU_Len (CHARCOUNT(szU) - 1)
  297. #define szUC_Len (CHARCOUNT(szUC) - 1)
  298. STDMETHODIMP CSelectFile::get_BrowseBtnCaption(BSTR *pVal)
  299. {
  300. // TODO: Add your implementation code here
  301. CComBSTR bstrCaption;
  302. wstring strCaption = m_BrowseBtnCaption;
  303. wstring::size_type nPos;
  304. nPos = m_BrowseBtnCaption.find(TEXT('&'));
  305. if (nPos == wstring::npos || nPos > m_BrowseBtnCaption.length() - 1) {
  306. bstrCaption = m_BrowseBtnCaption.c_str();
  307. } else {
  308. bstrCaption = m_BrowseBtnCaption.substr(0, nPos).c_str();
  309. bstrCaption += szU;
  310. bstrCaption += m_BrowseBtnCaption[nPos+1];
  311. bstrCaption += szUC;
  312. if (nPos < m_BrowseBtnCaption.length() - 1) {
  313. bstrCaption += m_BrowseBtnCaption.substr(nPos+2).c_str();
  314. }
  315. }
  316. *pVal = bstrCaption.Copy();
  317. return S_OK;
  318. }
  319. STDMETHODIMP CSelectFile::put_BrowseBtnCaption(BSTR newVal)
  320. {
  321. //
  322. // form a caption from the string
  323. //
  324. wstring strCaption = newVal;
  325. wstring strCaptionU = strCaption;
  326. wstring::size_type nPosU, nPosUC;
  327. wstring strAccel;
  328. StrUpCase(strCaptionU);
  329. //
  330. // find <u> </u> pair
  331. //
  332. nPosU = strCaptionU.find(szU);
  333. nPosUC = strCaptionU.find(szUC, nPosU);
  334. if (nPosUC == wstring::npos || nPosU == wstring::npos || nPosUC < nPosU || nPosUC <= (nPosU + szU_Len)) {
  335. goto cleanup;
  336. }
  337. // extract the char at the &
  338. //
  339. //
  340. strAccel = strCaption.substr(nPosU + szU_Len, nPosUC - (nPosU + szU_Len));
  341. //
  342. // add accel please -- with command id IDC_BROWSE
  343. //
  344. m_Accel.SetAccel(strAccel.c_str(), IDC_BROWSE);
  345. //
  346. // now we (presumably) found <u>accelchar</u>
  347. //
  348. m_BrowseBtnCaption = strCaption.substr(0, nPosU); // up to the <U>
  349. m_BrowseBtnCaption += TEXT('&');
  350. m_BrowseBtnCaption += strAccel.c_str();
  351. m_BrowseBtnCaption += strCaption.substr(nPosUC + szUC_Len); // all the rest please
  352. if (IsWindow()) {
  353. SetDlgItemText(IDC_BROWSE, m_BrowseBtnCaption.c_str());
  354. }
  355. cleanup:
  356. return S_OK;
  357. }
  358. STDMETHODIMP CSelectFile::get_AccelCmd(LONG lCmd, BSTR *pVal)
  359. {
  360. CComBSTR bstrVal = m_Accel.GetAccelString((WORD)lCmd).c_str();
  361. *pVal = bstrVal.Copy();
  362. return S_OK;
  363. }
  364. STDMETHODIMP CSelectFile::put_AccelCmd(LONG lCmd, BSTR newVal)
  365. {
  366. m_Accel.SetAccel(newVal, (WORD)lCmd);
  367. return S_OK;
  368. }
  369. STDMETHODIMP CSelectFile::ClearAccel()
  370. {
  371. m_Accel.ClearAccel();
  372. return S_OK;
  373. }
  374. STDMETHODIMP CSelectFile::ClearExternAccel()
  375. {
  376. m_ExternAccel.ClearAccel();
  377. return S_OK;
  378. }