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.

344 lines
8.1 KiB

  1. /* cmdlink.c - Handles command line/pseudo-link objects.
  2. */
  3. #include "packager.h"
  4. #include <shellapi.h>
  5. DECLSPEC_IMPORT BOOL SafeOpenPromptForPackager(HWND hwnd, PCWSTR pszFile, BOOL bFromCommandLine);
  6. DWORD CmlWaitForChildProc( LPVOID lpv )
  7. {
  8. if (WaitForSingleObject((HANDLE)lpv, INFINITE) == 0)
  9. {
  10. if (gfInvisible)
  11. {
  12. PostMessage(ghwndFrame, WM_SYSCOMMAND, SC_CLOSE, 0L);
  13. }
  14. }
  15. CloseHandle((HANDLE)lpv);
  16. return 0;
  17. }
  18. void _CmlExecute(LPCSTR pszFile, LPCSTR pszParams)
  19. {
  20. HRESULT hr;
  21. WCHAR szUrlName[MAX_PATH];
  22. WCHAR szDialogName[MAX_PATH];
  23. BOOL bResult;
  24. SHELLEXECUTEINFO sexi = {0};
  25. DWORD err = NO_ERROR;
  26. MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, pszFile, -1, szUrlName, ARRAYSIZE(szUrlName));
  27. StringCchCopyW(szDialogName, ARRAYSIZE(szDialogName), szUrlName);
  28. if(pszParams && *pszParams)
  29. {
  30. StringCchCatW(szDialogName, ARRAYSIZE(szDialogName), L" ");
  31. MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, pszParams, -1, szUrlName, ARRAYSIZE(szUrlName));
  32. StringCchCatW(szDialogName, ARRAYSIZE(szDialogName),szUrlName);
  33. }
  34. if(SafeOpenPromptForPackager(NULL, szDialogName, TRUE))
  35. {
  36. // Now we can execute the link file.
  37. sexi.cbSize = sizeof(sexi);
  38. sexi.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_FLAG_DDEWAIT | SEE_MASK_NOZONECHECKS ;
  39. sexi.lpFile = pszFile;
  40. sexi.lpParameters = pszParams;
  41. sexi.nShow = SW_SHOWNORMAL;
  42. if (ShellExecuteEx(&sexi))
  43. {
  44. if (sexi.hProcess != NULL)
  45. {
  46. // Start a thread to wait on the app and close packager once it has ended
  47. DWORD id;
  48. HANDLE hThd = CreateThread(NULL, 0, CmlWaitForChildProc, sexi.hProcess, 0, &id );
  49. if (hThd)
  50. {
  51. CloseHandle(hThd);
  52. }
  53. else
  54. {
  55. CloseHandle(sexi.hProcess);
  56. err = GetLastError();
  57. }
  58. }
  59. }
  60. else
  61. {
  62. err = GetLastError();
  63. }
  64. if (err != NO_ERROR)
  65. ErrorMessage((err == ERROR_NO_ASSOCIATION) ? E_FAILED_TO_FIND_ASSOCIATION : E_FAILED_TO_EXECUTE_COMMAND);
  66. }
  67. }
  68. /* CmlActivate() - Activate the command line/pseudo-linked file.
  69. */
  70. VOID CmlActivate(LPCML lpcml)
  71. {
  72. LPSTR pchTemp = lpcml->szCommand;
  73. CHAR chSave = 0;
  74. BOOL fInQuote = FALSE;
  75. /* skip leading spaces */
  76. while (*pchTemp && *pchTemp == CHAR_SPACE)
  77. pchTemp = CharNext(pchTemp);
  78. /* find first non-quoted space */
  79. for (; *pchTemp && (*pchTemp != CHAR_SPACE || fInQuote); pchTemp = CharNext(pchTemp))
  80. {
  81. if (*pchTemp == CHAR_QUOTE)
  82. {
  83. fInQuote = !fInQuote;
  84. }
  85. }
  86. if (*pchTemp)
  87. {
  88. chSave = *pchTemp;
  89. *pchTemp++ = 0;
  90. }
  91. DPRINT("packager: Calling ShellExecute");
  92. _CmlExecute(lpcml->szCommand, pchTemp);
  93. DPRINT("packager: Back from ShellExecute");
  94. if (chSave)
  95. *(--pchTemp) = chSave;
  96. }
  97. /* CmlClone() -
  98. */
  99. LPCML
  100. CmlClone(
  101. LPCML lpcml
  102. )
  103. {
  104. return CmlCreate(lpcml->szCommand, lpcml->fCmdIsLink);
  105. }
  106. /* CmlCreate() -
  107. */
  108. LPCML
  109. CmlCreateWorker(
  110. LPSTR lpstrCmd,
  111. BOOL fCmdIsLink,
  112. BOOL fFileName)
  113. {
  114. HANDLE hdata = NULL;
  115. LPCML lpcml = NULL;
  116. if (!(hdata = GlobalAlloc(GMEM_MOVEABLE, sizeof(CML))) ||
  117. !(lpcml = (LPCML)GlobalLock(hdata)))
  118. goto errRtn;
  119. // Store the data in the window itself
  120. lpcml->hdata = hdata;
  121. lpcml->fCmdIsLink = fCmdIsLink;
  122. /*
  123. * If it is not a single filename,
  124. * or the filename does not have a space in it,
  125. * or the 'filename' has double qoute characters in it, then
  126. * just copy it without quoting.
  127. */
  128. if (!fFileName || strchr( lpstrCmd, CHAR_SPACE ) == NULL ||
  129. strchr( lpstrCmd, CHAR_QUOTE ) != NULL)
  130. StringCchCopy(lpcml->szCommand, ARRAYSIZE(lpcml->szCommand), lpstrCmd);
  131. else {
  132. LPSTR psz = lpcml->szCommand;
  133. *psz++ = CHAR_QUOTE;
  134. StringCchCopy(psz, ARRAYSIZE(lpcml->szCommand) - 1, lpstrCmd);
  135. StringCchCat(lpcml->szCommand, ARRAYSIZE(lpcml->szCommand), SZ_QUOTE);
  136. }
  137. CmlFixBounds(lpcml);
  138. return lpcml;
  139. errRtn:
  140. ErrorMessage(E_FAILED_TO_CREATE_CHILD_WINDOW);
  141. if (lpcml)
  142. GlobalUnlock(hdata);
  143. if (hdata)
  144. GlobalFree(hdata);
  145. return NULL;
  146. }
  147. /* CmlDelete() - Wipe out the command line.
  148. */
  149. VOID
  150. CmlDelete(
  151. LPCML lpcml
  152. )
  153. {
  154. HANDLE hdata;
  155. if (lpcml)
  156. {
  157. GlobalUnlock(hdata = lpcml->hdata);
  158. GlobalFree(hdata);
  159. }
  160. }
  161. /* CmlDraw() - Draw the command line, centered nicely.
  162. */
  163. VOID
  164. CmlDraw(
  165. LPCML lpcml,
  166. HDC hdc,
  167. LPRECT lprc,
  168. INT xHSB,
  169. BOOL fFocus
  170. )
  171. {
  172. HFONT hfont;
  173. RECT rcFocus;
  174. CHAR szDesc[CBSTRINGMAX];
  175. CHAR szFile[CBCMDLINKMAX];
  176. CHAR szMessage[CBSTRINGMAX + CBCMDLINKMAX];
  177. RECT rc;
  178. hfont = SelectObject(hdc, ghfontChild);
  179. if (lpcml->fCmdIsLink)
  180. {
  181. LoadString(ghInst, IDS_LINKTOFILE, szDesc, CharCountOf(szDesc));
  182. StringCchCopy(szFile, ARRAYSIZE(szFile), lpcml->szCommand);
  183. Normalize(szFile);
  184. StringCchPrintf(szMessage, ARRAYSIZE(szMessage), szDesc, (LPSTR)szFile);
  185. DrawText(hdc, szMessage, -1, lprc, DT_SINGLELINE | DT_NOPREFIX |
  186. DT_CENTER | DT_VCENTER);
  187. if (fFocus)
  188. {
  189. rcFocus = *lprc;
  190. DrawText(hdc, szMessage, -1, &rcFocus, DT_CALCRECT | DT_SINGLELINE |
  191. DT_NOPREFIX | DT_LEFT | DT_TOP);
  192. OffsetRect(&rcFocus, (lprc->left + lprc->right - rcFocus.right) /
  193. 2, (lprc->top + lprc->bottom - rcFocus.bottom) / 2);
  194. DrawFocusRect(hdc, &rcFocus);
  195. }
  196. }
  197. else
  198. {
  199. rc = *lprc;
  200. // We should have scroll bars, the text is wider than the window
  201. if (rc.right < lpcml->rc.right)
  202. {
  203. rc.right = lpcml->rc.right;
  204. OffsetRect(&rc, -xHSB, 0);
  205. }
  206. DrawText(hdc, lpcml->szCommand, -1, &rc, DT_SINGLELINE | DT_NOPREFIX |
  207. DT_CENTER | DT_VCENTER);
  208. if (fFocus)
  209. DrawFocusRect(hdc, &rc);
  210. }
  211. if (hfont)
  212. SelectObject(hdc, hfont);
  213. }
  214. /* CmlFixBounds() -
  215. */
  216. VOID
  217. CmlFixBounds(
  218. LPCML lpcml
  219. )
  220. {
  221. HDC hdc;
  222. HFONT hfont;
  223. // Figure out how large the text region will be
  224. if (*lpcml->szCommand)
  225. {
  226. if (hdc = GetWindowDC(ghwndFrame))
  227. {
  228. hfont = SelectObject(hdc, ghfontChild);
  229. SetRect(&(lpcml->rc), 0, 0, 20000, 100);
  230. DrawText(hdc, lpcml->szCommand, -1, &(lpcml->rc), DT_CALCRECT |
  231. DT_WORDBREAK | DT_NOPREFIX | DT_SINGLELINE);
  232. if (hfont)
  233. SelectObject(hdc, hfont);
  234. ReleaseDC(ghwndFrame, hdc);
  235. }
  236. }
  237. else
  238. {
  239. SetRect(&(lpcml->rc), 0, 0, 0, 0);
  240. }
  241. PostMessage(ghwndPane[CONTENT], WM_FIXSCROLL, 0, 0L);
  242. }
  243. /* CmlReadFromNative() - Read a command line object from the native data.
  244. */
  245. LPCML
  246. CmlReadFromNative(
  247. LPSTR *lplpstr
  248. )
  249. {
  250. BOOL fCmdIsLink;
  251. WORD w;
  252. CHAR szCmd[CBCMDLINKMAX];
  253. MemRead(lplpstr, (LPSTR)&w, sizeof(WORD));
  254. fCmdIsLink = (BOOL)w;
  255. StringCchCopy(szCmd, ARRAYSIZE(szCmd), *lplpstr);
  256. *lplpstr += lstrlen(szCmd) + 1;
  257. return CmlCreate(szCmd, fCmdIsLink);
  258. }
  259. /* CmlWriteToNative() - Write a command line object to the native data.
  260. */
  261. DWORD
  262. CmlWriteToNative(
  263. LPCML lpcml,
  264. LPSTR *lplpstr
  265. )
  266. {
  267. WORD w;
  268. if (lplpstr)
  269. {
  270. w = (WORD)lpcml->fCmdIsLink;
  271. MemWrite(lplpstr, (LPSTR)&w, sizeof(WORD));
  272. MemWrite(lplpstr, (LPSTR)lpcml->szCommand,
  273. lstrlen(lpcml->szCommand) + 1);
  274. }
  275. return sizeof(WORD) + lstrlen(lpcml->szCommand) + 1;
  276. }