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.

440 lines
11 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File: cmmgr.cpp
  4. //
  5. // Module: CMMGR32.EXE
  6. //
  7. // Synopsis: Main file for the CM downlevel executable.
  8. //
  9. // Copyright (c) 1996-1999 Microsoft Corporation
  10. //
  11. // Author: quintinb Created header 08/17/99
  12. //
  13. //+----------------------------------------------------------------------------
  14. #include "cmmaster.h"
  15. //
  16. // Common CM includes
  17. //
  18. #include "cmtiming.h"
  19. BOOL InitArgs(
  20. LPTSTR pszCmdln,
  21. LPTSTR pszCmp,
  22. PDWORD pdwFlags
  23. );
  24. void CheckCmdArg(
  25. LPTSTR pszToken,
  26. LPTSTR pszCmp,
  27. PDWORD pdwFlags
  28. );
  29. HINSTANCE g_hInst;
  30. //+---------------------------------------------------------------------------
  31. //
  32. // Function: InitArgs
  33. //
  34. // Synopsis: Parses the command line arguments, return the connectoid name if
  35. // "dialing with connectoid"
  36. //
  37. // Arguments: pArgs - Pointer to global args struct
  38. // nArgC - number of command line arguments
  39. // ppszArgv - command arguments
  40. // pszConnectoid - Connectoid name as found on command line
  41. //
  42. // Returns: TRUE if succeed
  43. // FALSE otherwise
  44. //
  45. // History: byao Modified 5/8/97
  46. // Added handler for 'dialing with connectoid'
  47. //----------------------------------------------------------------------------
  48. BOOL InitArgs(
  49. LPTSTR pszCmdln,
  50. LPTSTR pszCmp,
  51. PDWORD pdwFlags
  52. )
  53. {
  54. LPTSTR pszCurr;
  55. LPTSTR pszToken;
  56. CMDLN_STATE state;
  57. // Parse the command line.
  58. state = CS_CHAR;
  59. pszCurr = pszToken = pszCmdln;
  60. do
  61. {
  62. switch (*pszCurr)
  63. {
  64. case TEXT(' '):
  65. if (state == CS_CHAR)
  66. {
  67. //
  68. // we found a token
  69. //
  70. *pszCurr = TEXT('\0');
  71. CheckCmdArg(pszToken, pszCmp, pdwFlags);
  72. *pszCurr = TEXT(' ');
  73. pszCurr = pszToken = CharNextU(pszCurr);
  74. state = CS_END_SPACE;
  75. continue;
  76. }
  77. else if (state == CS_END_SPACE || state == CS_END_QUOTE)
  78. {
  79. pszToken = CharNextU(pszToken);
  80. }
  81. break;
  82. case TEXT('\"'):
  83. if (state == CS_BEGIN_QUOTE)
  84. {
  85. //
  86. // we found a token
  87. //
  88. *pszCurr = TEXT('\0');
  89. //
  90. // skip the opening quote
  91. //
  92. pszToken = CharNextU(pszToken);
  93. CheckCmdArg(pszToken, pszCmp, pdwFlags);
  94. *pszCurr = TEXT('\"');
  95. pszCurr = pszToken = CharNextU(pszCurr);
  96. state = CS_END_QUOTE;
  97. continue;
  98. }
  99. else
  100. {
  101. state = CS_BEGIN_QUOTE;
  102. }
  103. break;
  104. case TEXT('\0'):
  105. if (state != CS_END_QUOTE)
  106. {
  107. CheckCmdArg(pszToken, pszCmp, pdwFlags);
  108. }
  109. state = CS_DONE;
  110. break;
  111. default:
  112. if (state == CS_END_SPACE || state == CS_END_QUOTE)
  113. {
  114. state = CS_CHAR;
  115. }
  116. break;
  117. }
  118. pszCurr = CharNextU(pszCurr);
  119. } while (state != CS_DONE);
  120. return TRUE;
  121. }
  122. //
  123. // determines the cmdline parameter.
  124. //
  125. void CheckCmdArg(
  126. LPTSTR pszToken,
  127. LPTSTR pszCmp,
  128. PDWORD pdwFlags
  129. )
  130. {
  131. struct
  132. {
  133. LPCTSTR pszArg;
  134. DWORD dwFlag;
  135. } ArgTbl[] = {
  136. {TEXT("/settings"),FL_PROPERTIES},
  137. {TEXT("/autodial"),FL_AUTODIAL},
  138. {TEXT("/unattended"), FL_UNATTENDED}, // unattended dial
  139. {NULL,0}};
  140. CMTRACE1(TEXT("Command line argument %s"), pszToken);
  141. //
  142. // Look through our table for a match and set flags accordingly.
  143. //
  144. for (size_t nIdx=0;ArgTbl[nIdx].pszArg;nIdx++)
  145. {
  146. if (lstrcmpiU(pszToken, ArgTbl[nIdx].pszArg) == 0)
  147. {
  148. MYDBGASSERT(!(*pdwFlags & ArgTbl[nIdx].dwFlag)); // only one of each please
  149. CMTRACE2(TEXT("InitArgs() parsed option %s, flag=0x%x."), pszToken, ArgTbl[nIdx].dwFlag);
  150. *pdwFlags |= ArgTbl[nIdx].dwFlag;
  151. break;
  152. }
  153. }
  154. //
  155. // If table is exhausted, then its a data argument.
  156. //
  157. if (!ArgTbl[nIdx].pszArg)
  158. {
  159. //
  160. // If this is the first data argument then it must be a profile
  161. // source, either a .CMP file, a "connectoid" (.CON file).
  162. //
  163. lstrcpyU(pszCmp, pszToken);
  164. }
  165. return;
  166. }
  167. //+----------------------------------------------------------------------------
  168. //
  169. // Function: WinMain
  170. //
  171. // Synopsis: Main entry point of the exe
  172. //
  173. // History: byao Modified 05/06/97
  174. // handle 'dialing with connectoid' and 'unattended dialing'
  175. //
  176. // quintinb Modified 05/12/99
  177. // bAllUsers for MSN to use cmmgr32.exe on both NT5 and win98SR1
  178. //
  179. //+----------------------------------------------------------------------------
  180. int WINAPI WinMain(HINSTANCE hInst,
  181. HINSTANCE hPrevInst,
  182. LPSTR /*pszCmdLine*/,
  183. int /*iCmdShow*/)
  184. {
  185. //
  186. // First Things First, lets initialize the U Api's
  187. //
  188. if (!InitUnicodeAPI())
  189. {
  190. //
  191. // Without our U api's we are going no where. Bail.
  192. //
  193. MessageBox(NULL, TEXT("Cmmgr32.exe Initialization Error: Unable to initialize Unicode to ANSI conversion layer, exiting."),
  194. TEXT("Connection Manager"), MB_OK | MB_ICONERROR);
  195. return FALSE;
  196. }
  197. LPTSTR pszCmdLine;
  198. CMTRACE(TEXT("====================================================="));
  199. CMTRACE1(TEXT(" CMMGR32.EXE - LOADING - Process ID is 0x%x "), GetCurrentProcessId());
  200. CMTRACE(TEXT("====================================================="));
  201. CM_SET_TIMING_INTERVAL("WinMain");
  202. //
  203. // Declare local vars
  204. //
  205. TCHAR szServiceName[RAS_MaxEntryName]; // service name
  206. TCHAR szCmp[MAX_PATH]; // cmp filename
  207. LPTSTR pszCL;
  208. DWORD dwExitCode = ERROR_SUCCESS;
  209. DWORD dwFlags = 0;
  210. DWORD dwSize;
  211. BOOL bAllUsers;
  212. LPCMDIALINFO lpCmInfo = NULL;
  213. #ifndef UNICODE
  214. LPWSTR pszwServiceName;
  215. #endif
  216. //
  217. // we can't use hInst if we're linked with libc. libc uses GetModuleHandle(NULL).
  218. //
  219. g_hInst = GetModuleHandleA(NULL);
  220. //
  221. // Expand any environment strings in the command line
  222. //
  223. dwSize = lstrlenU(GetCommandLine()) + 1;
  224. do
  225. {
  226. pszCmdLine = (LPTSTR)CmMalloc(sizeof(WCHAR)*dwSize);
  227. if (pszCmdLine)
  228. {
  229. DWORD dwRequiredSize = ExpandEnvironmentStringsU(GetCommandLine(), pszCmdLine, dwSize);
  230. if (0 == dwRequiredSize)
  231. {
  232. CMASSERTMSG(FALSE, TEXT("ExpandEnvironmentStrings Failed, exiting."));
  233. goto done;
  234. }
  235. else if (dwRequiredSize > dwSize)
  236. {
  237. //
  238. // Buffer not large enough. Try again.
  239. //
  240. dwSize = dwRequiredSize;
  241. CmFree(pszCmdLine);
  242. }
  243. else
  244. {
  245. //
  246. // It worked and was the correct size
  247. //
  248. break;
  249. }
  250. }
  251. else
  252. {
  253. CMASSERTMSG(FALSE, TEXT("Unable to CmMalloc Memory for the command line string, exiting."));
  254. goto done;
  255. }
  256. } while(1);
  257. //
  258. // Now process the command line
  259. //
  260. CmStrTrim(pszCmdLine);
  261. pszCL = pszCmdLine;
  262. //
  263. // Scan, and skip over, subsequent characters until
  264. // another double-quote or a null is encountered.
  265. //
  266. if (*pszCL == TEXT('\"'))
  267. {
  268. while (*(++pszCL) != TEXT('\"')
  269. && *pszCL)
  270. ;
  271. //
  272. // If we stopped on a double-quote (usual case), skip
  273. // over it.
  274. //
  275. if ( *pszCL == TEXT('\"') )
  276. pszCL++;
  277. }
  278. //
  279. // skip the spaces
  280. //
  281. while (*pszCL && *pszCL == TEXT(' '))
  282. pszCL++;
  283. //
  284. // Return here if command line is empty - ALL PLATFORMS !!!!!!!
  285. //
  286. if (pszCL[0] == TEXT('\0'))
  287. {
  288. LPTSTR pszMsg = CmFmtMsg(g_hInst, IDMSG_NOCMDLINE_MSG);
  289. LPTSTR pszTitle = CmFmtMsg(g_hInst, IDMSG_APP_TITLE);
  290. MessageBoxEx(NULL,pszMsg, pszTitle, MB_OK|MB_ICONSTOP, LANG_USER_DEFAULT);//13309
  291. CmFree(pszTitle);
  292. CmFree(pszMsg);
  293. dwExitCode = ERROR_WRONG_INFO_SPECIFIED;
  294. goto done;
  295. }
  296. //
  297. // Parse the command line options: Basically, this is to set
  298. // commandline option flags, as well as the profile filename
  299. //
  300. //
  301. // without libc, pszCmdLine in WinMain is empty.
  302. //
  303. if (!InitArgs(pszCL, szCmp, &dwFlags))
  304. {
  305. dwExitCode = GetLastError();
  306. goto done;
  307. }
  308. //
  309. // Get the service name from the CMP
  310. //
  311. if (!GetProfileInfo(szCmp, szServiceName))
  312. {
  313. CMTRACE(TEXT("WinMain() can't run without a profile on the command line."));
  314. LPTSTR pszMsg = CmFmtMsg(g_hInst, IDMSG_NOCMS_MSG);
  315. LPTSTR pszTitle = CmFmtMsg(g_hInst, IDMSG_APP_TITLE);
  316. MessageBoxEx(NULL, pszMsg, pszTitle, MB_OK|MB_ICONSTOP, LANG_USER_DEFAULT);//13309
  317. CmFree(pszMsg);
  318. CmFree(pszTitle);
  319. dwExitCode = ERROR_WRONG_INFO_SPECIFIED;
  320. goto done;
  321. }
  322. //
  323. // Always set the FL_DESKTOP flag when CMMGR is calling, it is more
  324. // efficient than checking the module filename inside CmCustomDialDlg
  325. //
  326. if (!(dwFlags & FL_DESKTOP))
  327. {
  328. dwFlags |= FL_DESKTOP;
  329. }
  330. //
  331. // Call CMDIAL as appropriate
  332. //
  333. lpCmInfo = (LPCMDIALINFO) CmMalloc(sizeof(CMDIALINFO));
  334. if (NULL == lpCmInfo)
  335. {
  336. dwExitCode = ERROR_NOT_ENOUGH_MEMORY;
  337. goto done;
  338. }
  339. lpCmInfo->dwCmFlags = dwFlags;
  340. //
  341. // Determine if this is an all user call based upon the path.
  342. // Thus we can support single-user profiles on NT5.
  343. //
  344. bAllUsers = IsCmpPathAllUser(szCmp);
  345. CmCustomDialDlg(NULL,
  346. bAllUsers ? RCD_AllUsers : RCD_SingleUser,
  347. NULL,
  348. szServiceName,
  349. NULL,
  350. NULL,
  351. NULL,
  352. lpCmInfo);
  353. done:
  354. UnInitUnicodeAPI();
  355. CmFree(pszCmdLine);
  356. CmFree(lpCmInfo);
  357. CMTRACE(TEXT("====================================================="));
  358. CMTRACE1(TEXT(" CMMGR32.EXE - UNLOADING - Process ID is 0x%x "), GetCurrentProcessId());
  359. CMTRACE(TEXT("====================================================="));
  360. //
  361. // the C runtine uses ExitProcess() to exit.
  362. //
  363. ExitProcess((UINT)dwExitCode);
  364. return ((int)dwExitCode);
  365. }