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.

651 lines
13 KiB

  1. /*++
  2. Copyright (c) 1990-2003 Microsoft Corporation
  3. All Rights Reserved
  4. Module Name:
  5. util.c
  6. // @@BEGIN_DDKSPLIT
  7. Abstract:
  8. This module provides all the utility functions for localmon.
  9. Revision History:
  10. // @@END_DDKSPLIT
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. //
  15. // These globals are needed so that AddPort can call
  16. // SPOOLSS!EnumPorts to see whether the port to be added
  17. // already exists.
  18. // @@BEGIN_DDKSPLIT
  19. // They will be initialized the first time AddPort is called.
  20. //
  21. // !! LATER !!
  22. //
  23. // This is common code. move PortExists into the router.
  24. //
  25. // @@END_DDKSPLIT
  26. HMODULE hSpoolssDll = NULL;
  27. FARPROC pfnSpoolssEnumPorts = NULL;
  28. VOID
  29. LcmRemoveColon(
  30. LPWSTR pName)
  31. {
  32. DWORD Length;
  33. Length = wcslen(pName);
  34. if (pName[Length-1] == L':')
  35. pName[Length-1] = 0;
  36. }
  37. BOOL
  38. IsCOMPort(
  39. LPWSTR pPort
  40. )
  41. {
  42. //
  43. // Must begin with szLcmCOM
  44. //
  45. if ( _wcsnicmp( pPort, szLcmCOM, 3 ) )
  46. {
  47. return FALSE;
  48. }
  49. //
  50. // wcslen guarenteed >= 3
  51. //
  52. return pPort[ wcslen( pPort ) - 1 ] == L':';
  53. }
  54. BOOL
  55. IsLPTPort(
  56. LPWSTR pPort
  57. )
  58. {
  59. //
  60. // Must begin with szLcmLPT
  61. //
  62. if ( _wcsnicmp( pPort, szLcmLPT, 3 ) )
  63. {
  64. return FALSE;
  65. }
  66. //
  67. // wcslen guarenteed >= 3
  68. //
  69. return pPort[ wcslen( pPort ) - 1 ] == L':';
  70. }
  71. #define NEXTVAL(pch) \
  72. while( *pch && ( *pch != L',' ) ) \
  73. pch++; \
  74. if( *pch ) \
  75. pch++
  76. BOOL
  77. GetIniCommValues(
  78. LPWSTR pName,
  79. LPDCB pdcb,
  80. LPCOMMTIMEOUTS pcto
  81. )
  82. {
  83. BOOL bRet = FALSE;
  84. DWORD rc, dwCharCount = 10;
  85. LPVOID pszEntry = NULL;
  86. do {
  87. FreeSplMem(pszEntry);
  88. dwCharCount *= 2;
  89. pszEntry = AllocSplMem(dwCharCount*sizeof(WCHAR));
  90. if ( !pszEntry ||
  91. !(rc = GetProfileString(szPorts, pName, szNULL,
  92. pszEntry, dwCharCount)) )
  93. goto Done;
  94. } while ( rc >= dwCharCount - 2 );
  95. bRet = BuildCommDCB((LPWSTR)pszEntry, pdcb);
  96. pcto->WriteTotalTimeoutConstant = GetProfileInt(szWindows,
  97. szINIKey_TransmissionRetryTimeout,
  98. 45 );
  99. pcto->WriteTotalTimeoutConstant*=1000;
  100. Done:
  101. FreeSplMem(pszEntry);
  102. return bRet;
  103. }
  104. /* PortExists
  105. *
  106. * Calls EnumPorts to check whether the port name already exists.
  107. * This asks every monitor, rather than just this one.
  108. * The function will return TRUE if the specified port is in the list.
  109. * If an error occurs, the return is FALSE and the variable pointed
  110. * to by pError contains the return from GetLastError().
  111. * The caller must therefore always check that *pError == NO_ERROR.
  112. */
  113. BOOL
  114. PortExists(
  115. LPWSTR pName,
  116. LPWSTR pPortName,
  117. PDWORD pError
  118. )
  119. {
  120. DWORD cbNeeded;
  121. DWORD cReturned;
  122. DWORD cbPorts;
  123. LPPORT_INFO_1 pPorts;
  124. DWORD i;
  125. BOOL Found = TRUE;
  126. *pError = NO_ERROR;
  127. if (!hSpoolssDll) {
  128. hSpoolssDll = LoadLibrary(L"SPOOLSS.DLL");
  129. if (hSpoolssDll) {
  130. pfnSpoolssEnumPorts = GetProcAddress(hSpoolssDll,
  131. "EnumPortsW");
  132. if (!pfnSpoolssEnumPorts) {
  133. *pError = GetLastError();
  134. FreeLibrary(hSpoolssDll);
  135. hSpoolssDll = NULL;
  136. }
  137. } else {
  138. *pError = GetLastError();
  139. }
  140. }
  141. if (!pfnSpoolssEnumPorts)
  142. return FALSE;
  143. if (!(*pfnSpoolssEnumPorts)(pName, 1, NULL, 0, &cbNeeded, &cReturned))
  144. {
  145. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  146. {
  147. cbPorts = cbNeeded;
  148. pPorts = AllocSplMem(cbPorts);
  149. if (pPorts)
  150. {
  151. if ((*pfnSpoolssEnumPorts)(pName, 1, (LPBYTE)pPorts, cbPorts,
  152. &cbNeeded, &cReturned))
  153. {
  154. Found = FALSE;
  155. for (i = 0; i < cReturned; i++)
  156. {
  157. if (!lstrcmpi(pPorts[i].pName, pPortName))
  158. Found = TRUE;
  159. }
  160. }
  161. }
  162. FreeSplMem(pPorts);
  163. }
  164. }
  165. else
  166. Found = FALSE;
  167. return Found;
  168. }
  169. VOID
  170. LcmSplInSem(
  171. VOID
  172. )
  173. {
  174. if (LcmSpoolerSection.OwningThread != (HANDLE) UIntToPtr(GetCurrentThreadId())) {
  175. DBGMSG(DBG_ERROR, ("Not in spooler semaphore\n"));
  176. }
  177. }
  178. VOID
  179. LcmSplOutSem(
  180. VOID
  181. )
  182. {
  183. if (LcmSpoolerSection.OwningThread == (HANDLE) UIntToPtr(GetCurrentThreadId())) {
  184. DBGMSG(DBG_ERROR, ("Inside spooler semaphore !!\n"));
  185. }
  186. }
  187. VOID
  188. LcmEnterSplSem(
  189. VOID
  190. )
  191. {
  192. EnterCriticalSection(&LcmSpoolerSection);
  193. }
  194. VOID
  195. LcmLeaveSplSem(
  196. VOID
  197. )
  198. {
  199. #if DBG
  200. LcmSplInSem();
  201. #endif
  202. LeaveCriticalSection(&LcmSpoolerSection);
  203. }
  204. PINIENTRY
  205. LcmFindName(
  206. PINIENTRY pIniKey,
  207. LPWSTR pName
  208. )
  209. {
  210. if (pName) {
  211. while (pIniKey) {
  212. if (!lstrcmpi(pIniKey->pName, pName)) {
  213. return pIniKey;
  214. }
  215. pIniKey=pIniKey->pNext;
  216. }
  217. }
  218. return FALSE;
  219. }
  220. PINIENTRY
  221. LcmFindIniKey(
  222. PINIENTRY pIniEntry,
  223. LPWSTR pName
  224. )
  225. {
  226. if (!pName)
  227. return NULL;
  228. LcmSplInSem();
  229. while (pIniEntry && lstrcmpi(pName, pIniEntry->pName))
  230. pIniEntry = pIniEntry->pNext;
  231. return pIniEntry;
  232. }
  233. LPBYTE
  234. PackStrings(
  235. LPWSTR *pSource,
  236. LPBYTE pDest,
  237. DWORD *DestOffsets,
  238. LPBYTE pEnd
  239. )
  240. {
  241. while (*DestOffsets != -1) {
  242. if (*pSource) {
  243. size_t cbString = wcslen(*pSource)*sizeof(WCHAR) + sizeof(WCHAR);
  244. pEnd-= cbString;
  245. StringCbCopy ((LPWSTR) pEnd, cbString, *pSource);;
  246. *(LPWSTR UNALIGNED *)(pDest+*DestOffsets)= (LPWSTR) pEnd;
  247. } else
  248. *(LPWSTR UNALIGNED *)(pDest+*DestOffsets)=0;
  249. pSource++;
  250. DestOffsets++;
  251. }
  252. return pEnd;
  253. }
  254. /* LcmMessage
  255. *
  256. * Displays a LcmMessage by loading the strings whose IDs are passed into
  257. * the function, and substituting the supplied variable argument list
  258. * using the varargs macros.
  259. *
  260. */
  261. int LcmMessage(HWND hwnd, DWORD Type, int CaptionID, int TextID, ...)
  262. {
  263. WCHAR MsgText[256];
  264. WCHAR MsgFormat[256];
  265. WCHAR MsgCaption[40];
  266. va_list vargs;
  267. if( ( LoadString( LcmhInst, TextID, MsgFormat,
  268. sizeof MsgFormat / sizeof *MsgFormat ) > 0 )
  269. && ( LoadString( LcmhInst, CaptionID, MsgCaption,
  270. sizeof MsgCaption / sizeof *MsgCaption ) > 0 ) )
  271. {
  272. va_start( vargs, TextID );
  273. StringCchVPrintf (MsgText, COUNTOF (MsgText), MsgFormat, vargs );
  274. va_end( vargs );
  275. return MessageBox(hwnd, MsgText, MsgCaption, Type);
  276. }
  277. else
  278. return 0;
  279. }
  280. /*
  281. *
  282. */
  283. LPTSTR
  284. LcmGetErrorString(
  285. DWORD Error
  286. )
  287. {
  288. TCHAR Buffer[1024];
  289. LPTSTR pErrorString = NULL;
  290. if( FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM,
  291. NULL, Error, 0, Buffer,
  292. COUNTOF(Buffer), NULL )
  293. == 0 )
  294. LoadString( LcmhInst, IDS_UNKNOWN_ERROR,
  295. Buffer, COUNTOF(Buffer) );
  296. pErrorString = AllocSplStr(Buffer);
  297. return pErrorString;
  298. }
  299. DWORD ReportError( HWND hwndParent,
  300. DWORD idTitle,
  301. DWORD idDefaultError )
  302. {
  303. DWORD ErrorID;
  304. DWORD MsgType;
  305. LPTSTR pErrorString;
  306. ErrorID = GetLastError( );
  307. if( ErrorID == ERROR_ACCESS_DENIED )
  308. MsgType = MSG_INFORMATION;
  309. else
  310. MsgType = MSG_ERROR;
  311. pErrorString = LcmGetErrorString( ErrorID );
  312. LcmMessage( hwndParent, MsgType, idTitle,
  313. idDefaultError, pErrorString );
  314. FreeSplStr( pErrorString );
  315. return ErrorID;
  316. }
  317. // @@BEGIN_DDKSPLIT
  318. #ifndef INTERNAL
  319. // @@END_DDKSPLIT
  320. LPWSTR
  321. AllocSplStr(
  322. LPWSTR pStr
  323. )
  324. /*++
  325. Routine Description:
  326. This function will allocate enough local memory to store the specified
  327. string, and copy that string to the allocated memory
  328. Arguments:
  329. pStr - Pointer to the string that needs to be allocated and stored
  330. Return Value:
  331. NON-NULL - A pointer to the allocated memory containing the string
  332. FALSE/NULL - The operation failed. Extended error status is available
  333. using GetLastError.
  334. --*/
  335. {
  336. LPWSTR pMem;
  337. DWORD cbStr;
  338. if (!pStr) {
  339. return NULL;
  340. }
  341. cbStr = wcslen(pStr)*sizeof(WCHAR) + sizeof(WCHAR);
  342. if (pMem = AllocSplMem( cbStr )) {
  343. CopyMemory( pMem, pStr, cbStr );
  344. }
  345. return pMem;
  346. }
  347. LPVOID
  348. AllocSplMem(
  349. DWORD cbAlloc
  350. )
  351. {
  352. PVOID pvMemory;
  353. pvMemory = GlobalAlloc(GMEM_FIXED, cbAlloc);
  354. if( pvMemory ){
  355. ZeroMemory( pvMemory, cbAlloc );
  356. }
  357. return pvMemory;
  358. }
  359. // @@BEGIN_DDKSPLIT
  360. #endif
  361. // @@END_DDKSPLIT
  362. DWORD
  363. WINAPIV
  364. StrNCatBuffW(
  365. IN PWSTR pszBuffer,
  366. IN UINT cchBuffer,
  367. ...
  368. )
  369. /*++
  370. Description:
  371. This routine concatenates a set of null terminated strings
  372. into the provided buffer. The last argument must be a NULL
  373. to signify the end of the argument list. This only called
  374. from LocalMon by functions that use WCHARS.
  375. Arguments:
  376. pszBuffer - pointer buffer where to place the concatenated
  377. string.
  378. cchBuffer - character count of the provided buffer including
  379. the null terminator.
  380. ... - variable number of string to concatenate.
  381. Returns:
  382. ERROR_SUCCESS if new concatenated string is returned,
  383. or ERROR_XXX if an error occurred.
  384. Notes:
  385. The caller must pass valid strings as arguments to this routine,
  386. if an integer or other parameter is passed the routine will either
  387. crash or fail abnormally. Since this is an internal routine
  388. we are not in try except block for performance reasons.
  389. --*/
  390. {
  391. DWORD dwRetval = ERROR_INVALID_PARAMETER;
  392. PCWSTR pszTemp = NULL;
  393. PWSTR pszDest = NULL;
  394. va_list pArgs;
  395. //
  396. // Validate the pointer where to return the buffer.
  397. //
  398. if (pszBuffer && cchBuffer)
  399. {
  400. //
  401. // Assume success.
  402. //
  403. dwRetval = ERROR_SUCCESS;
  404. //
  405. // Get pointer to argument frame.
  406. //
  407. va_start(pArgs, cchBuffer);
  408. //
  409. // Get temp destination pointer.
  410. //
  411. pszDest = pszBuffer;
  412. //
  413. // Insure we have space for the null terminator.
  414. //
  415. cchBuffer--;
  416. //
  417. // Collect all the arguments.
  418. //
  419. for ( ; ; )
  420. {
  421. //
  422. // Get pointer to the next argument.
  423. //
  424. pszTemp = va_arg(pArgs, PCWSTR);
  425. if (!pszTemp)
  426. {
  427. break;
  428. }
  429. //
  430. // Copy the data into the destination buffer.
  431. //
  432. for ( ; cchBuffer; cchBuffer-- )
  433. {
  434. if (!(*pszDest = *pszTemp))
  435. {
  436. break;
  437. }
  438. pszDest++, pszTemp++;
  439. }
  440. //
  441. // If were unable to write all the strings to the buffer,
  442. // set the error code and nuke the incomplete copied strings.
  443. //
  444. if (!cchBuffer && pszTemp && *pszTemp)
  445. {
  446. dwRetval = ERROR_BUFFER_OVERFLOW;
  447. *pszBuffer = L'\0';
  448. break;
  449. }
  450. }
  451. //
  452. // Terminate the buffer always.
  453. //
  454. *pszDest = L'\0';
  455. va_end(pArgs);
  456. }
  457. //
  458. // Set the last error in case the caller forgets to.
  459. //
  460. if (dwRetval != ERROR_SUCCESS)
  461. {
  462. SetLastError(dwRetval);
  463. }
  464. return dwRetval;
  465. }
  466. /* PortIsValid
  467. *
  468. * Validate the port by attempting to create/open it.
  469. */
  470. BOOL
  471. PortIsValid(
  472. LPWSTR pPortName
  473. )
  474. {
  475. HANDLE hFile;
  476. BOOL Valid;
  477. //
  478. // For COM and LPT ports, no verification
  479. //
  480. if ( IS_COM_PORT( pPortName ) ||
  481. IS_LPT_PORT( pPortName ) ||
  482. IS_FILE_PORT( pPortName ) )
  483. {
  484. return TRUE;
  485. }
  486. hFile = CreateFile(pPortName,
  487. GENERIC_WRITE,
  488. FILE_SHARE_READ,
  489. NULL,
  490. OPEN_EXISTING,
  491. FILE_ATTRIBUTE_NORMAL,
  492. NULL);
  493. if (hFile == INVALID_HANDLE_VALUE) {
  494. hFile = CreateFile(pPortName,
  495. GENERIC_WRITE,
  496. FILE_SHARE_READ,
  497. NULL,
  498. OPEN_ALWAYS,
  499. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE,
  500. NULL);
  501. }
  502. if (hFile != INVALID_HANDLE_VALUE) {
  503. CloseHandle(hFile);
  504. Valid = TRUE;
  505. } else {
  506. Valid = FALSE;
  507. }
  508. return Valid;
  509. }