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.

1795 lines
40 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. string.c
  5. Abstract:
  6. This file implements string functions for fax.
  7. Author:
  8. Wesley Witt (wesw) 23-Jan-1995
  9. Environment:
  10. User Mode
  11. --*/
  12. #include <windows.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <tchar.h>
  16. #include <ObjBase.h>
  17. #include "faxutil.h"
  18. #include "fxsapip.h"
  19. #define SECURITY_WIN32 // needed by security.h
  20. #include <Security.h>
  21. #include "faxreg.h"
  22. #include "FaxUIConstants.h"
  23. #define STRSAFE_NO_DEPRECATE
  24. #include <strsafe.h>
  25. LPTSTR
  26. AllocateAndLoadString(
  27. HINSTANCE hInstance,
  28. UINT uID
  29. )
  30. /*++
  31. Routine Description:
  32. Calls LoadString for given HINSTANCE and ID of the string.
  33. Allocates memory in loop to find enough memory.
  34. Returns the given string.
  35. The caller must free the string.
  36. Arguments:
  37. hInstance - module instance
  38. uID - ID of the string to bring
  39. Return Value:
  40. the allocated string, NULL if error.
  41. Call GetLastError() for the details.
  42. Author:
  43. Iv Garber, 22-Oct-2000
  44. --*/
  45. {
  46. LPTSTR lptstrResult = NULL;
  47. DWORD dwNumCopiedChars = 0;
  48. DWORD dwSize = 100;
  49. do
  50. {
  51. //
  52. // There is not enough place for all the string
  53. //
  54. dwSize = dwSize * 3;
  55. MemFree(lptstrResult);
  56. //
  57. // Allocate memory for the string
  58. //
  59. lptstrResult = LPTSTR(MemAlloc(dwSize * sizeof(TCHAR)));
  60. if (!lptstrResult)
  61. {
  62. return NULL;
  63. }
  64. //
  65. // Bring the string from the resource file
  66. //
  67. dwNumCopiedChars = LoadString(hInstance, uID, lptstrResult, dwSize);
  68. if (!dwNumCopiedChars)
  69. {
  70. //
  71. // the string does not exist in the resource file
  72. //
  73. SetLastError(ERROR_INVALID_PARAMETER);
  74. MemFree(lptstrResult);
  75. return NULL;
  76. }
  77. } while(dwNumCopiedChars == (dwSize - 1));
  78. return lptstrResult;
  79. }
  80. LPTSTR
  81. StringDup(
  82. LPCTSTR String
  83. )
  84. {
  85. LPTSTR NewString;
  86. if (!String) {
  87. return NULL;
  88. }
  89. NewString = (LPTSTR) MemAlloc( (_tcslen( String ) + 1) * sizeof(TCHAR) );
  90. if (!NewString) {
  91. return NULL;
  92. }
  93. _tcscpy( NewString, String );
  94. return NewString;
  95. }
  96. LPWSTR
  97. StringDupW(
  98. LPCWSTR String
  99. )
  100. {
  101. LPWSTR NewString;
  102. if (!String) {
  103. return NULL;
  104. }
  105. NewString = (LPWSTR) MemAlloc( (wcslen( String ) + 1) * sizeof(WCHAR) );
  106. if (!NewString) {
  107. return NULL;
  108. }
  109. wcscpy( NewString, String );
  110. return NewString;
  111. }
  112. int MultiStringDup(PSTRING_PAIR lpPairs, int nPairCount)
  113. {
  114. int i,j;
  115. Assert(lpPairs);
  116. for (i=0;i<nPairCount;i++) {
  117. if (lpPairs[i].lptstrSrc) {
  118. *(lpPairs[i].lpptstrDst)=StringDup(lpPairs[i].lptstrSrc);
  119. if (!*(lpPairs[i].lpptstrDst)) {
  120. // Cleanup the strings we did copy so far.
  121. for (j=0;j<i;j++) {
  122. MemFree(*(lpPairs[j].lpptstrDst));
  123. *(lpPairs[j].lpptstrDst) = NULL;
  124. }
  125. // return the index in which we failed + 1 (0 is success so we can not use it).
  126. return i+1;
  127. }
  128. }
  129. }
  130. return 0;
  131. }
  132. VOID
  133. FreeString(
  134. LPVOID String
  135. )
  136. {
  137. MemFree( String );
  138. }
  139. LPWSTR
  140. AnsiStringToUnicodeString(
  141. LPCSTR AnsiString
  142. )
  143. {
  144. DWORD Count;
  145. LPWSTR UnicodeString;
  146. if (!AnsiString)
  147. return NULL;
  148. //
  149. // first see how big the buffer needs to be
  150. //
  151. Count = MultiByteToWideChar(
  152. CP_ACP,
  153. MB_PRECOMPOSED,
  154. AnsiString,
  155. -1,
  156. NULL,
  157. 0
  158. );
  159. //
  160. // i guess the input string is empty
  161. //
  162. if (!Count) {
  163. return NULL;
  164. }
  165. //
  166. // allocate a buffer for the unicode string
  167. //
  168. Count += 1;
  169. UnicodeString = (LPWSTR) MemAlloc( Count * sizeof(UNICODE_NULL) );
  170. if (!UnicodeString) {
  171. return NULL;
  172. }
  173. //
  174. // convert the string
  175. //
  176. Count = MultiByteToWideChar(
  177. CP_ACP,
  178. MB_PRECOMPOSED,
  179. AnsiString,
  180. -1,
  181. UnicodeString,
  182. Count
  183. );
  184. //
  185. // the conversion failed
  186. //
  187. if (!Count) {
  188. MemFree( UnicodeString );
  189. return NULL;
  190. }
  191. return UnicodeString;
  192. }
  193. LPSTR
  194. UnicodeStringToAnsiString(
  195. LPCWSTR UnicodeString
  196. )
  197. {
  198. DWORD Count;
  199. LPSTR AnsiString;
  200. if (!UnicodeString)
  201. return NULL;
  202. //
  203. // first see how big the buffer needs to be
  204. //
  205. Count = WideCharToMultiByte(
  206. CP_ACP,
  207. 0,
  208. UnicodeString,
  209. -1,
  210. NULL,
  211. 0,
  212. NULL,
  213. NULL
  214. );
  215. //
  216. // i guess the input string is empty
  217. //
  218. if (!Count) {
  219. return NULL;
  220. }
  221. //
  222. // allocate a buffer for the unicode string
  223. //
  224. Count += 1;
  225. AnsiString = (LPSTR) MemAlloc( Count );
  226. if (!AnsiString) {
  227. return NULL;
  228. }
  229. //
  230. // convert the string
  231. //
  232. Count = WideCharToMultiByte(
  233. CP_ACP,
  234. 0,
  235. UnicodeString,
  236. -1,
  237. AnsiString,
  238. Count,
  239. NULL,
  240. NULL
  241. );
  242. //
  243. // the conversion failed
  244. //
  245. if (!Count) {
  246. MemFree( AnsiString );
  247. return NULL;
  248. }
  249. return AnsiString;
  250. }
  251. BOOL
  252. MakeDirectory(
  253. LPCTSTR Dir
  254. )
  255. /*++
  256. Routine Description:
  257. Attempt to create all of the directories in the given path.
  258. Arguments:
  259. Dir - Directory path to create
  260. Return Value:
  261. TRUE for success, FALSE on error
  262. --*/
  263. {
  264. LPTSTR p, NewDir;
  265. DWORD ec = ERROR_SUCCESS;
  266. DWORD dwFileAtt;
  267. DEBUG_FUNCTION_NAME(TEXT("MakeDirectory"));
  268. NewDir = p = ExpandEnvironmentString( Dir );
  269. if (!NewDir)
  270. {
  271. ec = GetLastError();
  272. DebugPrintEx(
  273. DEBUG_ERR,
  274. TEXT("ExpandEnvironmentString (private function) failed. (ec: %ld)"),
  275. ec);
  276. goto Exit;
  277. }
  278. dwFileAtt = GetFileAttributes( NewDir );
  279. if (-1 != dwFileAtt && (dwFileAtt & FILE_ATTRIBUTE_DIRECTORY))
  280. {
  281. //
  282. // The directory exists
  283. //
  284. ec = ERROR_SUCCESS;
  285. goto Exit;
  286. }
  287. if ( (_tcsclen(p) > 2) && (_tcsncmp(p,TEXT("\\\\"),2) == 0) )
  288. {
  289. //
  290. // Path name start with UNC (\\)
  291. // Skip first double backslash (\\)
  292. //
  293. p = _tcsninc(p,2);
  294. //
  295. // Scan until the end of the server name
  296. //
  297. if( p = _tcschr(p,TEXT('\\')) )
  298. {
  299. //
  300. // Skip the server name
  301. //
  302. p = _tcsinc(p);
  303. //
  304. // Scan until the end of the share name
  305. //
  306. if( p = _tcschr(p,TEXT('\\')) )
  307. {
  308. //
  309. // Skip the share name
  310. //
  311. p = _tcsinc(p);
  312. }
  313. }
  314. }
  315. else if ( (_tcsclen(p) > 1) && (_tcsncmp(p,TEXT("\\"),1) == 0) )
  316. {
  317. //
  318. // Path name starts with root directory (e.g. : "\blah\blah2") - skip it
  319. //
  320. p = _tcsinc(p);
  321. }
  322. else if ( (_tcsclen(p) > 3) &&
  323. _istalpha(p[0]) &&
  324. (_tcsncmp(_tcsinc(p),TEXT(":\\"),2) == 0) )
  325. {
  326. //
  327. // Path name starts with drive and root directory (e.g. : "c:\blah\blah2") - skip it
  328. //
  329. p = _tcsninc(p,3);
  330. }
  331. if (NULL == p)
  332. {
  333. //
  334. // Reached EOSTR
  335. //
  336. if (!CreateDirectory( NewDir, NULL ))
  337. {
  338. //
  339. // Check if we failed because the dir already existed.
  340. // If so this is not an error.
  341. //
  342. ec = GetLastError();
  343. if (ERROR_ALREADY_EXISTS != ec)
  344. {
  345. DebugPrintEx(
  346. DEBUG_ERR,
  347. TEXT("CreateDirectory [%s] failed (ec: %ld)"),
  348. NewDir,
  349. ec);
  350. }
  351. else
  352. {
  353. ec = ERROR_SUCCESS;
  354. }
  355. goto Exit;
  356. }
  357. }
  358. while( *(p = _tcsinc(p)) )
  359. {
  360. p = _tcschr(p,TEXT('\\'));
  361. if( !p )
  362. {
  363. //
  364. // Reached EOSTR
  365. //
  366. if (!CreateDirectory( NewDir, NULL ))
  367. {
  368. //
  369. // Check if we failed because the dir already existed.
  370. // If so this is not an error.
  371. //
  372. if (ERROR_ALREADY_EXISTS != GetLastError())
  373. {
  374. ec = GetLastError();
  375. DebugPrintEx(
  376. DEBUG_ERR,
  377. TEXT("CreateDirectory [%s] failed (ec: %ld)"),
  378. NewDir,
  379. ec);
  380. }
  381. }
  382. break; // success case
  383. }
  384. //
  385. // Place NULL instead of backslash
  386. //
  387. p[0] = TEXT('\0');
  388. if (!CreateDirectory( NewDir, NULL ))
  389. {
  390. //
  391. // Check if we failed because the dir already existed.
  392. // If so this is not an error.
  393. //
  394. if (ERROR_ALREADY_EXISTS != GetLastError())
  395. {
  396. ec = GetLastError();
  397. DebugPrintEx(
  398. DEBUG_ERR,
  399. TEXT("CreateDirectory [%s] failed (ec: %ld)"),
  400. NewDir,
  401. ec);
  402. break;
  403. }
  404. }
  405. //
  406. // Restore backslash
  407. //
  408. p[0] = TEXT('\\');
  409. }
  410. Exit:
  411. MemFree( NewDir );
  412. if (ERROR_SUCCESS != ec)
  413. {
  414. SetLastError(ec);
  415. }
  416. return (ERROR_SUCCESS == ec);
  417. }
  418. VOID
  419. HideDirectory(
  420. LPTSTR Dir
  421. )
  422. /*++
  423. Routine Description:
  424. Hide the specified directory
  425. Arguments:
  426. Dir - Directory path to hide
  427. Return Value:
  428. none.
  429. --*/
  430. {
  431. DWORD attrib;
  432. //
  433. // make sure it exists
  434. //
  435. if (!Dir) {
  436. return;
  437. }
  438. MakeDirectory( Dir );
  439. attrib = GetFileAttributes(Dir);
  440. if (attrib == 0xFFFFFFFF) {
  441. return;
  442. }
  443. attrib |= FILE_ATTRIBUTE_HIDDEN;
  444. SetFileAttributes( Dir, attrib );
  445. return;
  446. }
  447. VOID
  448. DeleteDirectory(
  449. LPTSTR Dir
  450. )
  451. /*++
  452. Routine Description:
  453. Attempt to delete all of the directories in the given path.
  454. Arguments:
  455. Dir - Directory path to delete
  456. Return Value:
  457. TRUE for success, FALSE on error
  458. --*/
  459. {
  460. LPTSTR p;
  461. while (true)
  462. {
  463. if (!RemoveDirectory( Dir ))
  464. {
  465. return;
  466. }
  467. // get a pointer to the end of Dir
  468. p = _tcschr(Dir,TEXT('\0'));
  469. p = _tcsdec(Dir,p);
  470. //
  471. // If p is equal to ( or less then ) Dir, _tscdec returns NULL
  472. //
  473. if (!p)
  474. {
  475. return;
  476. }
  477. while ( _tcsncmp(p,TEXT("\\"),1) && p != Dir )
  478. {
  479. p = _tcsdec(Dir,p);
  480. }
  481. if (p == Dir)
  482. {
  483. return;
  484. }
  485. _tcsnset(p,TEXT('\0'),1);
  486. }
  487. } // DeleteDirectory
  488. int
  489. FormatElapsedTimeStr(
  490. FILETIME *ElapsedTime,
  491. LPTSTR TimeStr,
  492. DWORD StringSize
  493. )
  494. /*++
  495. Routine Description:
  496. Convert ElapsedTime to a string.
  497. Arguments:
  498. ElaspedTime - the elapsed time
  499. TimeStr - buffer to store the string into
  500. StringSize - size of the buffer in TCHARS
  501. Return Value:
  502. The return value of GetTimeFormat()
  503. --*/
  504. {
  505. SYSTEMTIME SystemTime;
  506. FileTimeToSystemTime( ElapsedTime, &SystemTime );
  507. return FaxTimeFormat(
  508. LOCALE_SYSTEM_DEFAULT,
  509. LOCALE_NOUSEROVERRIDE | TIME_FORCE24HOURFORMAT | TIME_NOTIMEMARKER,
  510. &SystemTime,
  511. NULL,
  512. TimeStr,
  513. StringSize
  514. );
  515. }
  516. LPTSTR
  517. ExpandEnvironmentString(
  518. LPCTSTR EnvString
  519. )
  520. {
  521. DWORD dwRes;
  522. DWORD Size;
  523. LPTSTR String;
  524. DEBUG_FUNCTION_NAME(TEXT("ExpandEnvironmentString"));
  525. if(!_tcschr(EnvString, '%'))
  526. {
  527. //
  528. // On Win95 ExpandEnvironmentStrings fails if sting
  529. // doesn't contain environment variable.
  530. //
  531. String = StringDup(EnvString);
  532. if(!String)
  533. {
  534. DebugPrintEx(DEBUG_ERR, TEXT("StringDup failed"));
  535. return NULL;
  536. }
  537. else
  538. {
  539. return String;
  540. }
  541. }
  542. Size = ExpandEnvironmentStrings( EnvString, NULL, 0 );
  543. if (Size == 0)
  544. {
  545. dwRes = GetLastError();
  546. DebugPrintEx(DEBUG_ERR, TEXT("ExpandEnvironmentStrings failed: 0x%08X)"), dwRes);
  547. return NULL;
  548. }
  549. ++Size;
  550. String = (LPTSTR) MemAlloc( Size * sizeof(TCHAR) );
  551. if (String == NULL)
  552. {
  553. DebugPrintEx(DEBUG_ERR, TEXT("MemAlloc failed"));
  554. return NULL;
  555. }
  556. if (ExpandEnvironmentStrings( EnvString, String, Size ) == 0)
  557. {
  558. dwRes = GetLastError();
  559. DebugPrintEx(DEBUG_ERR, TEXT("ExpandEnvironmentStrings failed: 0x%08X)"), dwRes);
  560. MemFree( String );
  561. return NULL;
  562. }
  563. return String;
  564. }
  565. LPTSTR
  566. GetEnvVariable(
  567. LPCTSTR EnvString
  568. )
  569. {
  570. DWORD Size;
  571. LPTSTR EnvVar;
  572. Size = GetEnvironmentVariable( EnvString, NULL, 0 );
  573. if (!Size) {
  574. return NULL;
  575. }
  576. EnvVar = (LPTSTR) MemAlloc( Size * sizeof(TCHAR) );
  577. if (EnvVar == NULL) {
  578. return NULL;
  579. }
  580. Size = GetEnvironmentVariable( EnvString, EnvVar, Size );
  581. if (!Size) {
  582. MemFree( EnvVar );
  583. return NULL;
  584. }
  585. return EnvVar;
  586. }
  587. int
  588. GetY2KCompliantDate (
  589. LCID Locale,
  590. DWORD dwFlags,
  591. CONST SYSTEMTIME *lpDate,
  592. LPTSTR lpDateStr,
  593. int cchDate
  594. )
  595. {
  596. int iRes;
  597. DEBUG_FUNCTION_NAME(TEXT("GetY2KCompliantDate()"));
  598. iRes = GetDateFormat(Locale,
  599. dwFlags,
  600. lpDate,
  601. NULL,
  602. lpDateStr,
  603. cchDate);
  604. if (!iRes)
  605. {
  606. //
  607. // If failed, no need to care about the formatted date string
  608. //
  609. return iRes;
  610. }
  611. if (0 == cchDate)
  612. {
  613. //
  614. // User only wants to know the output string size.
  615. //
  616. // We return a bigger size than GetDateFormat() returns,
  617. // because the DATE_LTRREADING flag we sometimes add later,
  618. // might enlarge the result string.
  619. // Although we don't always use the DATE_LTRREADING flag (only used in Win2K and only
  620. // if the string has right-to-left characters), we always return a bigger required
  621. // buffer size - just to make the code simpler.
  622. //
  623. return iRes * 2;
  624. }
  625. #if (WINVER >= 0x0500)
  626. #ifdef UNICODE
  627. //
  628. // If the formatted date string contains right-to-left characters
  629. // for example, in Hebrew, Arabic etc. languages
  630. // then the system fails to write it correctly.
  631. //
  632. // So, we want to enforce right-to-left direction in this case
  633. //
  634. // This is possible only for WINVER>=0x0500
  635. // For any other OS nothing can be done.
  636. //
  637. if ( (dwFlags & DATE_RTLREADING) || (dwFlags & DATE_LTRREADING) )
  638. {
  639. //
  640. // the caller defined a direction, nothing needs to be added
  641. //
  642. return iRes;
  643. }
  644. OSVERSIONINFO osVerInfo;
  645. osVerInfo.dwOSVersionInfoSize = sizeof(osVerInfo);
  646. if (!GetVersionEx(&osVerInfo))
  647. {
  648. DebugPrintEx(DEBUG_ERR, _T("GetVersionEx() failed : %ld"), GetLastError());
  649. return 0;
  650. }
  651. if ( (osVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) && (osVerInfo.dwMajorVersion >= 5) )
  652. {
  653. //
  654. // Get direction information about the characters in the formatted date string
  655. //
  656. if (StrHasRTLChar(Locale, lpDateStr))
  657. {
  658. //
  659. // There is at least one Right-To-Left character
  660. // So, we need to add Right-To-Left marks to the whole string
  661. //
  662. iRes = GetDateFormat(Locale,
  663. dwFlags | DATE_RTLREADING,
  664. lpDate,
  665. NULL,
  666. lpDateStr,
  667. cchDate);
  668. }
  669. }
  670. #endif // UNICODE
  671. #endif // (WINVER >= 0x0500)
  672. return iRes;
  673. } // GetY2KCompliantDate
  674. DWORD
  675. IsValidGUID (
  676. LPCWSTR lpcwstrGUID
  677. )
  678. /*++
  679. Routine name : IsValidGUID
  680. Routine description:
  681. Checks validity of a GUID string
  682. Author:
  683. Eran Yariv (EranY), Nov, 1999
  684. Arguments:
  685. lpcwstrGUID [in ] - GUID string to check for validity
  686. Return Value:
  687. ERROR_SUCCESS if valid GUID string.
  688. Win32 error otherwise.
  689. --*/
  690. {
  691. GUID guid;
  692. HRESULT hr;
  693. DEBUG_FUNCTION_NAME(TEXT("IsValidGUID"));
  694. hr = CLSIDFromString((LPOLESTR)lpcwstrGUID, &guid);
  695. if (FAILED(hr) && hr != REGDB_E_WRITEREGDB )
  696. {
  697. if (CO_E_CLASSSTRING == hr)
  698. {
  699. //
  700. // Invalid GUID
  701. //
  702. DebugPrintEx(
  703. DEBUG_ERR,
  704. TEXT("GUID [%s] is invalid"),
  705. lpcwstrGUID);
  706. return ERROR_WMI_GUID_NOT_FOUND;
  707. }
  708. else
  709. {
  710. DebugPrintEx(
  711. DEBUG_ERR,
  712. TEXT("CLSIDFromString for GUID [%s] has failed (hr: 0x%08X)"),
  713. lpcwstrGUID,
  714. hr);
  715. return ERROR_GEN_FAILURE;
  716. }
  717. }
  718. return ERROR_SUCCESS;
  719. } // IsValidGUID
  720. //*****************************************************************************
  721. //* Name: StoreString
  722. //* Author:
  723. //*****************************************************************************
  724. //* DESCRIPTION:
  725. //* Copies a string to an offset within a buffer and updates the offset
  726. //* to refelect the length of the copied string. Used for filling out
  727. //* pointerless buffers (i.e. using offset to start of buffer instead of
  728. //* pointers to memory locations).
  729. //* PARAMETERS:
  730. //* [IN] String:
  731. //* The string to be copied.
  732. //* [OUT] DestString:
  733. //* Points to a variable that should be assigned the offset
  734. //* at which the string was copied.
  735. //* [IN] Buffer
  736. //* A pointer to the buffer into which the string should be copied.
  737. //* [IN] Offset
  738. //* A pointer to a variable that holds the offset from the start
  739. //* of the buffer where the string is to be copied (0 based).
  740. //* On successful return the value of this variable is increased
  741. //* by the length of the string (not including null).
  742. //* The new offset can be used to copy the next string just after
  743. //* the terminatng null of the last copied string.
  744. //* [IN] dwBufferSize
  745. //* Size of the buffer Buffer, in bytes.
  746. //* This parameter is used only if Buffer is not NULL.
  747. //*
  748. //* RETURN VALUE:
  749. //* None
  750. //* Comments:
  751. //* None.
  752. //*****************************************************************************
  753. VOID
  754. StoreString(
  755. LPCTSTR String,
  756. PULONG_PTR DestString,
  757. LPBYTE Buffer,
  758. PULONG_PTR Offset,
  759. DWORD dwBufferSize
  760. )
  761. {
  762. if (String)
  763. {
  764. Assert(Offset);
  765. if (Buffer)
  766. {
  767. Assert(DestString);
  768. if ( dwBufferSize <= *Offset ||
  769. (dwBufferSize - *Offset) < StringSize( String ))
  770. {
  771. ASSERT_FALSE;
  772. }
  773. HRESULT hr = StringCbCopy( (LPTSTR) (Buffer+*Offset),
  774. dwBufferSize - *Offset,
  775. String);
  776. if (FAILED(hr))
  777. {
  778. ASSERT_FALSE;
  779. // In case of insufficient buffer we write a truncated string
  780. //
  781. }
  782. *DestString = *Offset;
  783. }
  784. *Offset += StringSize( String );
  785. }
  786. else
  787. {
  788. if (Buffer)
  789. {
  790. Assert(DestString);
  791. *DestString = 0;
  792. }
  793. }
  794. }
  795. VOID
  796. StoreStringW(
  797. LPCWSTR String,
  798. PULONG_PTR DestString,
  799. LPBYTE Buffer,
  800. PULONG_PTR Offset,
  801. DWORD dwBufferSize
  802. )
  803. {
  804. if (String)
  805. {
  806. Assert(Offset);
  807. if (Buffer)
  808. {
  809. Assert(DestString);
  810. if ( dwBufferSize <= *Offset ||
  811. (dwBufferSize - *Offset) < StringSizeW( String ))
  812. {
  813. ASSERT_FALSE;
  814. }
  815. HRESULT hr = StringCbCopyW( (LPWSTR) (Buffer+*Offset),
  816. dwBufferSize - *Offset,
  817. String);
  818. if (FAILED(hr))
  819. {
  820. ASSERT_FALSE;
  821. // In case of insufficient buffer we write a truncated string
  822. //
  823. }
  824. *DestString = *Offset;
  825. }
  826. *Offset += StringSizeW( String );
  827. }
  828. else
  829. {
  830. if (Buffer)
  831. {
  832. Assert(DestString);
  833. *DestString = 0;
  834. }
  835. }
  836. }
  837. DWORD
  838. IsCanonicalAddress(
  839. LPCTSTR lpctstrAddress,
  840. BOOL* lpbRslt,
  841. LPDWORD lpdwCountryCode,
  842. LPDWORD lpdwAreaCode,
  843. LPCTSTR* lppctstrSubNumber
  844. )
  845. /*++
  846. Routine name : IsCanonicalAddress
  847. Routine description:
  848. Checks if an address is canonical.
  849. Returns the country code, area code, and the rest of the number.
  850. If it is succsfull the caller must free the rest the subscriber number (if requested).
  851. Author:
  852. Oded Sacher (OdedS), Dec, 1999
  853. Arguments:
  854. lpctstrAddress [in ] - Pointer to a null terminated string containing the address.
  855. lpbRslt [out] - Pointer to a BOOL to recieve whether the address is canonical.
  856. Valid only if the function did not fail.
  857. lpdwCountryCode [out] - Pointer to a DWORD to recieve the country code (Can be NULL).
  858. Return value is valid only if lpbRslt is TRUE.
  859. lpdwAreaCode [out] - Pointer to a DWORD to recieve the area code (Can be NULL).
  860. Return value is valid only if lpbRslt is TRUE.
  861. lppctstrSubNumber [out] - Pointer to a LPCTSTR to recieve the subsriber number (Can be NULL).
  862. If it is not NULL, and the return value is TRUE, Call MemFree to deallocate memory.
  863. Return Value:
  864. Standard win32 error code.
  865. --*/
  866. {
  867. DWORD dwRes = ERROR_SUCCESS;
  868. LPTSTR lptstrSubNumber = NULL;
  869. DWORD dwStringSize, dwScanedArg, dwCountryCode, dwAreaCode;
  870. BOOL bFreeSubNumber = TRUE;
  871. DEBUG_FUNCTION_NAME(TEXT("IsCanonicalAddress"));
  872. dwStringSize = (_tcslen(lpctstrAddress) + 1) * sizeof(TCHAR);
  873. lptstrSubNumber = (LPTSTR)MemAlloc (dwStringSize);
  874. if (NULL == lptstrSubNumber)
  875. {
  876. DebugPrintEx(
  877. DEBUG_ERR,
  878. TEXT("failed to allocate memory"));
  879. return ERROR_OUTOFMEMORY;
  880. }
  881. if (NULL == _tcschr(lpctstrAddress, TEXT('(')))
  882. {
  883. dwScanedArg = _stscanf (lpctstrAddress,
  884. TEXT("+%lu%*1[' ']%[^'\0']"),
  885. &dwCountryCode,
  886. lptstrSubNumber);
  887. if (2 != dwScanedArg)
  888. {
  889. *lpbRslt = FALSE;
  890. goto exit;
  891. }
  892. dwAreaCode = ROUTING_RULE_AREA_CODE_ANY;
  893. }
  894. else
  895. {
  896. dwScanedArg = _stscanf (lpctstrAddress,
  897. TEXT("+%lu%*1[' '](%lu)%*1[' ']%[^'\0']"),
  898. &dwCountryCode,
  899. &dwAreaCode,
  900. lptstrSubNumber);
  901. if (3 != dwScanedArg)
  902. {
  903. *lpbRslt = FALSE;
  904. goto exit;
  905. }
  906. }
  907. if (NULL != _tcschr(lptstrSubNumber, TEXT('(')))
  908. {
  909. *lpbRslt = FALSE;
  910. goto exit;
  911. }
  912. if (NULL != lpdwCountryCode)
  913. {
  914. *lpdwCountryCode = dwCountryCode;
  915. }
  916. if (NULL != lpdwAreaCode)
  917. {
  918. *lpdwAreaCode = dwAreaCode;
  919. }
  920. if (NULL != lppctstrSubNumber)
  921. {
  922. *lppctstrSubNumber = lptstrSubNumber;
  923. bFreeSubNumber = FALSE;
  924. }
  925. *lpbRslt = TRUE;
  926. Assert (ERROR_SUCCESS == dwRes);
  927. exit:
  928. if (TRUE == bFreeSubNumber)
  929. {
  930. MemFree (lptstrSubNumber);
  931. }
  932. return dwRes;
  933. } // IsCanonicalAddress
  934. BOOL
  935. IsValidFaxAddress (
  936. LPCTSTR lpctstrFaxAddress,
  937. BOOL bAllowCanonicalFormat
  938. )
  939. /*++
  940. Routine name : IsValidFaxAddress
  941. Routine description:
  942. Checks if a given string is a valid fax address
  943. Author:
  944. Eran Yariv (EranY), Apr, 2001
  945. Arguments:
  946. lpctstrFaxAddress [in] - String to check
  947. bAllowCanonicalFormat [in] - Allow string to be of canonical format.
  948. If string is in a canonical format, only the sub-address is checked.
  949. Return Value:
  950. TRUE if string is a valid fax address, FALSE otherwise.
  951. --*/
  952. {
  953. BOOL bCanonical;
  954. BOOL bRes = FALSE;
  955. LPCTSTR lpctstrSubAddress = lpctstrFaxAddress;
  956. DEBUG_FUNCTION_NAME(TEXT("IsValidFaxAddress"));
  957. if (bAllowCanonicalFormat)
  958. {
  959. //
  960. // Check an see if the address is canonical
  961. //
  962. if (ERROR_SUCCESS != IsCanonicalAddress (lpctstrFaxAddress, &bCanonical, NULL, NULL, &lpctstrSubAddress))
  963. {
  964. //
  965. // Can't detect canonical state - return invalid address
  966. //
  967. return FALSE;
  968. }
  969. if (!bCanonical)
  970. {
  971. //
  972. // Analyse entire string
  973. //
  974. lpctstrSubAddress = lpctstrFaxAddress;
  975. }
  976. }
  977. //
  978. // Scan for occurance of characters NOT in valid set
  979. //
  980. if (NULL == _tcsspnp (lpctstrSubAddress, FAX_ADDERSS_VALID_CHARACTERS))
  981. {
  982. //
  983. // Address string contains only valid characters
  984. //
  985. bRes = TRUE;
  986. goto exit;
  987. }
  988. //
  989. // Found an illegal character - return FALSE
  990. //
  991. exit:
  992. if (lpctstrSubAddress && lpctstrSubAddress != lpctstrFaxAddress)
  993. {
  994. MemFree ((LPVOID)lpctstrSubAddress);
  995. }
  996. return bRes;
  997. } // IsValidFaxAddress
  998. BOOL
  999. IsLocalMachineNameA (
  1000. LPCSTR lpcstrMachineName
  1001. )
  1002. /*++
  1003. Routine name : IsLocalMachineNameA
  1004. Routine description:
  1005. Checks if a given string points to the local machine.
  1006. ANSII version.
  1007. Author:
  1008. Eran Yariv (EranY), Jul, 2000
  1009. Arguments:
  1010. lpcstrMachineName [in] - String input
  1011. Return Value:
  1012. TRUE if given string points to the local machine, FALSE otherwise.
  1013. --*/
  1014. {
  1015. CHAR szComputerName[MAX_COMPUTERNAME_LENGTH + 1];
  1016. DWORD dwBufLen = MAX_COMPUTERNAME_LENGTH + 1;
  1017. DEBUG_FUNCTION_NAME(TEXT("IsLocalMachineNameA"));
  1018. if (!lpcstrMachineName)
  1019. {
  1020. //
  1021. // NULL is local
  1022. //
  1023. return TRUE;
  1024. }
  1025. if (!strlen(lpcstrMachineName))
  1026. {
  1027. //
  1028. // Empty string is local
  1029. //
  1030. return TRUE;
  1031. }
  1032. if (!strcmp (".", lpcstrMachineName))
  1033. {
  1034. //
  1035. // "." is local
  1036. //
  1037. return TRUE;
  1038. }
  1039. if (!GetComputerNameA (szComputerName, &dwBufLen))
  1040. {
  1041. DebugPrintEx(
  1042. DEBUG_ERR,
  1043. TEXT("GetComputerNameA failed with %ld"),
  1044. GetLastError());
  1045. return FALSE;
  1046. }
  1047. if (!_stricmp (szComputerName, lpcstrMachineName))
  1048. {
  1049. //
  1050. // Same string as computer name
  1051. //
  1052. return TRUE;
  1053. }
  1054. return FALSE;
  1055. } // IsLocalMachineNameA
  1056. BOOL
  1057. IsLocalMachineNameW (
  1058. LPCWSTR lpcwstrMachineName
  1059. )
  1060. /*++
  1061. Routine name : IsLocalMachineNameW
  1062. Routine description:
  1063. Checks if a given string points to the local machine.
  1064. UNICODE version.
  1065. Author:
  1066. Eran Yariv (EranY), Jul, 2000
  1067. Arguments:
  1068. lpcwstrMachineName [in] - String input
  1069. Return Value:
  1070. TRUE if given string points to the local machine, FALSE otherwise.
  1071. --*/
  1072. {
  1073. WCHAR wszComputerName[MAX_COMPUTERNAME_LENGTH + 1];
  1074. DWORD dwBufLen = MAX_COMPUTERNAME_LENGTH + 1;
  1075. DEBUG_FUNCTION_NAME(TEXT("IsLocalMachineNameW"));
  1076. if (!lpcwstrMachineName)
  1077. {
  1078. //
  1079. // NULL is local
  1080. //
  1081. return TRUE;
  1082. }
  1083. if (!wcslen(lpcwstrMachineName))
  1084. {
  1085. //
  1086. // Empty string is local
  1087. //
  1088. return TRUE;
  1089. }
  1090. if (!wcscmp (L".", lpcwstrMachineName))
  1091. {
  1092. //
  1093. // "." is local
  1094. //
  1095. return TRUE;
  1096. }
  1097. if (!GetComputerNameW (wszComputerName, &dwBufLen))
  1098. {
  1099. DebugPrintEx(
  1100. DEBUG_ERR,
  1101. TEXT("GetComputerNameA failed with %ld"),
  1102. GetLastError());
  1103. return FALSE;
  1104. }
  1105. if (!_wcsicmp (wszComputerName, lpcwstrMachineName))
  1106. {
  1107. //
  1108. // Same string as computer name
  1109. //
  1110. return TRUE;
  1111. }
  1112. return FALSE;
  1113. } // IsLocalMachineNameW
  1114. //+--------------------------------------------------------------------------
  1115. //
  1116. // Function: GetSecondsFreeTimeFormat (former UpdateTimeFormat)
  1117. //
  1118. // Synopsis: Construct a time format containing hour and minute for use
  1119. // with the date picker control.
  1120. //
  1121. // Arguments: [tszTimeFormat] - buffer to fill with time format
  1122. // [cchTimeFormat] - size in chars of buffer
  1123. //
  1124. // Modifies: *[tszTimeFormat]
  1125. //
  1126. // History: After 11-18-1996 DavidMun UpdateTimeFormat
  1127. //
  1128. //
  1129. //---------------------------------------------------------------------------
  1130. void
  1131. GetSecondsFreeTimeFormat(
  1132. LPTSTR tszTimeFormat,
  1133. ULONG cchTimeFormat)
  1134. {
  1135. DEBUG_FUNCTION_NAME( _T("GetSecondsFreeTimeFormat"));
  1136. DWORD ec = ERROR_SUCCESS;
  1137. ULONG cch = 0;
  1138. TCHAR tszScratch[100];
  1139. BOOL fAmPm;
  1140. BOOL fAmPmPrefixes;
  1141. BOOL fLeadingZero;
  1142. TCHAR tszDefaultTimeFormat[] = { TEXT("hh:mm tt") };
  1143. //
  1144. // 1) GetLocal info
  1145. //
  1146. //
  1147. // AM/PM (0) or 24H (1)
  1148. //
  1149. if (0 == GetLocaleInfo( LOCALE_USER_DEFAULT,
  1150. LOCALE_ITIME,
  1151. tszScratch,
  1152. sizeof(tszScratch)/sizeof(tszScratch[0])))
  1153. {
  1154. ec = GetLastError();
  1155. DebugPrintEx(
  1156. DEBUG_ERR,
  1157. _T("Failed to GetLocaleInfo for LOCALE_ITIME. (ec: %ld)"),
  1158. ec);
  1159. if (ERROR_INSUFFICIENT_BUFFER == ec)
  1160. {
  1161. Assert(FALSE);
  1162. }
  1163. goto Error;
  1164. }
  1165. fAmPm = (*tszScratch == TEXT('0'));
  1166. if (fAmPm)
  1167. {
  1168. //
  1169. // AM/PM as suffix (0) as prefix (1)
  1170. //
  1171. if (0 == GetLocaleInfo( LOCALE_USER_DEFAULT,
  1172. LOCALE_ITIMEMARKPOSN,
  1173. tszScratch,
  1174. sizeof(tszScratch)/sizeof(tszScratch[0])))
  1175. {
  1176. ec = GetLastError();
  1177. DebugPrintEx(
  1178. DEBUG_ERR,
  1179. _T("Failed to GetLocaleInfo for LOCALE_ITIMEMARKPOSN. (ec: %ld)"),
  1180. ec);
  1181. if (ERROR_INSUFFICIENT_BUFFER == ec)
  1182. {
  1183. Assert(FALSE);
  1184. }
  1185. goto Error;
  1186. }
  1187. fAmPmPrefixes = (*tszScratch == TEXT('1'));
  1188. }
  1189. //
  1190. // Leading zeros for hours: no (0) yes (1)
  1191. //
  1192. if (0 == GetLocaleInfo( LOCALE_USER_DEFAULT,
  1193. LOCALE_ITLZERO,
  1194. tszScratch,
  1195. sizeof(tszScratch)/sizeof(tszScratch[0])))
  1196. {
  1197. ec = GetLastError();
  1198. DebugPrintEx(
  1199. DEBUG_ERR,
  1200. _T("Failed to GetLocaleInfo for LOCALE_ITLZERO. (ec: %ld)"),
  1201. ec);
  1202. if (ERROR_INSUFFICIENT_BUFFER == ec)
  1203. {
  1204. Assert(FALSE);
  1205. }
  1206. goto Error;
  1207. }
  1208. fLeadingZero = (*tszScratch == TEXT('1'));
  1209. //
  1210. // Get Charcter(s) for time seperator
  1211. //
  1212. if (0 == GetLocaleInfo( LOCALE_USER_DEFAULT,
  1213. LOCALE_STIME,
  1214. tszScratch,
  1215. sizeof(tszScratch)/sizeof(tszScratch[0])))
  1216. {
  1217. ec = GetLastError();
  1218. DebugPrintEx(
  1219. DEBUG_ERR,
  1220. _T("Failed to GetLocaleInfo for LOCALE_STIME. (ec: %ld)"),
  1221. ec);
  1222. if (ERROR_INSUFFICIENT_BUFFER == ec)
  1223. {
  1224. Assert(FALSE);
  1225. }
  1226. goto Error;
  1227. }
  1228. //
  1229. // See if there's enough room in destination string
  1230. //
  1231. cch = 1 + // terminating nul
  1232. 1 + // first hour digit specifier "h"
  1233. 2 + // minutes specifier "mm"
  1234. (fLeadingZero != 0) + // leading hour digit specifier "h"
  1235. lstrlen(tszScratch) + // separator string
  1236. (fAmPm ? 3 : 0); // space and "tt" for AM/PM
  1237. if (cch > cchTimeFormat)
  1238. {
  1239. cch = 0; // signal error
  1240. DebugPrintEx(
  1241. DEBUG_ERR,
  1242. _T("Time format too long."));
  1243. goto Error;
  1244. }
  1245. Assert(cch);
  1246. //
  1247. // 2) Build a time string that has hours and minutes but no seconds.
  1248. //
  1249. tszTimeFormat[0] = TEXT('\0');
  1250. if (fAmPm)
  1251. {
  1252. if (fAmPmPrefixes)
  1253. {
  1254. lstrcpy(tszTimeFormat, TEXT("tt "));
  1255. }
  1256. lstrcat(tszTimeFormat, TEXT("h"));
  1257. if (fLeadingZero)
  1258. {
  1259. lstrcat(tszTimeFormat, TEXT("h"));
  1260. }
  1261. }
  1262. else
  1263. {
  1264. lstrcat(tszTimeFormat, TEXT("H"));
  1265. if (fLeadingZero)
  1266. {
  1267. lstrcat(tszTimeFormat, TEXT("H"));
  1268. }
  1269. }
  1270. lstrcat(tszTimeFormat, tszScratch); // separator
  1271. lstrcat(tszTimeFormat, TEXT("mm"));
  1272. if (fAmPm && !fAmPmPrefixes)
  1273. {
  1274. lstrcat(tszTimeFormat, TEXT(" tt"));
  1275. }
  1276. return;
  1277. Error:
  1278. //
  1279. // If there was a problem in getting locale info for building time string
  1280. // just use the default and bail.
  1281. //
  1282. Assert (!cch);
  1283. lstrcpyn(tszTimeFormat, tszDefaultTimeFormat,cchTimeFormat);
  1284. DebugPrintEx(
  1285. DEBUG_ERR,
  1286. _T("Failed to GET_LOCALE_INFO set tszDefaultTimeFormat."));
  1287. return;
  1288. }
  1289. /*++
  1290. Routine name : MultiStringSize
  1291. Description:
  1292. Helper function to find Multi-String size (UNICODE or ANSI)
  1293. MultiString (as in registry REG_MULTY_SZ type) is stored as a series of zero-terminated string,
  1294. with two zero charcters terminating the final string in the series.
  1295. Multi-String have to be at least 2 characters long!!!
  1296. Author:
  1297. Caliv Nir, FEB , 2001
  1298. Arguments:
  1299. psz - [IN] - input multi-string (must be leggal multi-string otherwise result are undefined)
  1300. Return Value:
  1301. string length including the terminating zero !!!
  1302. --*/
  1303. size_t MultiStringLength(LPCTSTR psz)
  1304. {
  1305. LPCTSTR pszT = psz;
  1306. Assert ( psz );
  1307. if ( !psz[0] ) psz+=1; // empty string as a first string skip it
  1308. while (*psz)
  1309. psz += lstrlen(psz) + 1;
  1310. return psz - pszT + 1; // one additional zero-terminator
  1311. }
  1312. LPCTSTR
  1313. GetRegisteredOrganization ()
  1314. /*++
  1315. Routine name : GetRegisteredOrganization
  1316. Routine description:
  1317. Retrieves the system's registered company name (organization)
  1318. Author:
  1319. Eran Yariv (EranY), Apr, 2001
  1320. Arguments:
  1321. Return Value:
  1322. Allocated result string
  1323. --*/
  1324. {
  1325. DEBUG_FUNCTION_NAME( _T("GetRegisteredOrganization"));
  1326. LPTSTR lptstrRes = NULL;
  1327. HKEY hKey = NULL;
  1328. hKey = OpenRegistryKey (HKEY_LOCAL_MACHINE,
  1329. REGKEY_INSTALLLOCATION,
  1330. FALSE,
  1331. KEY_QUERY_VALUE);
  1332. if (!hKey)
  1333. {
  1334. DebugPrintEx(
  1335. DEBUG_ERR,
  1336. TEXT("OpenRegistryKey failed with %ld"),
  1337. GetLastError());
  1338. return StringDup(TEXT(""));
  1339. }
  1340. lptstrRes = GetRegistryString (hKey,
  1341. TEXT("RegisteredOrganization"),
  1342. TEXT(""));
  1343. RegCloseKey (hKey);
  1344. return lptstrRes;
  1345. } // GetRegisteredOrganization
  1346. LPCTSTR
  1347. GetCurrentUserName ()
  1348. /*++
  1349. Routine name : GetCurrentUserName
  1350. Routine description:
  1351. Retrieves display name of the current user
  1352. Author:
  1353. Eran Yariv (EranY), Apr, 2001
  1354. Arguments:
  1355. Return Value:
  1356. Allocated result string
  1357. --*/
  1358. {
  1359. DEBUG_FUNCTION_NAME( _T("GetCurrentUserName"));
  1360. TCHAR tszName[MAX_PATH] = TEXT("");
  1361. DWORD dwSize = ARR_SIZE(tszName);
  1362. typedef BOOLEAN (SEC_ENTRY * PFNGETUSERNAMEXA)(EXTENDED_NAME_FORMAT, LPSTR, PULONG);
  1363. typedef BOOLEAN (SEC_ENTRY * PFNGETUSERNAMEXW)(EXTENDED_NAME_FORMAT, LPWSTR, PULONG);
  1364. HMODULE hMod = LoadLibrary (TEXT("Secur32.dll"));
  1365. if (hMod)
  1366. {
  1367. #ifdef UNICODE
  1368. PFNGETUSERNAMEXW pfnGetUserNameEx = (PFNGETUSERNAMEXW)GetProcAddress (hMod, "GetUserNameExW");
  1369. #else
  1370. PFNGETUSERNAMEXA pfnGetUserNameEx = (PFNGETUSERNAMEXA)GetProcAddress (hMod, "GetUserNameExA");
  1371. #endif
  1372. if (pfnGetUserNameEx)
  1373. {
  1374. if (!pfnGetUserNameEx(NameDisplay, tszName, &dwSize))
  1375. {
  1376. DebugPrintEx(
  1377. DEBUG_ERR,
  1378. TEXT("GetUserNameEx failed with %ld"),
  1379. GetLastError());
  1380. }
  1381. }
  1382. else
  1383. {
  1384. DebugPrintEx(
  1385. DEBUG_ERR,
  1386. TEXT("GetProcAddress failed with %ld"),
  1387. GetLastError());
  1388. }
  1389. FreeLibrary (hMod);
  1390. }
  1391. else
  1392. {
  1393. DebugPrintEx(
  1394. DEBUG_ERR,
  1395. TEXT("LoadLibrary(secur32.dll) failed with %ld"),
  1396. GetLastError());
  1397. }
  1398. return StringDup(tszName);
  1399. } // GetCurrentUserName
  1400. BOOL
  1401. IsValidSubscriberIdW (
  1402. LPCWSTR lpcwstrSubscriberId
  1403. )
  1404. {
  1405. DEBUG_FUNCTION_NAME(TEXT("IsValidSubscriberIdW"));
  1406. CHAR szAnsiiSID[FXS_TSID_CSID_MAX_LENGTH + 1];
  1407. CHAR cDefaultChar = 19;
  1408. Assert (lpcwstrSubscriberId);
  1409. if(wcslen (lpcwstrSubscriberId) > FXS_TSID_CSID_MAX_LENGTH)
  1410. {
  1411. return FALSE;
  1412. }
  1413. if (!WideCharToMultiByte (CP_ACP,
  1414. 0,
  1415. lpcwstrSubscriberId,
  1416. -1,
  1417. szAnsiiSID,
  1418. sizeof (szAnsiiSID),
  1419. &cDefaultChar,
  1420. NULL))
  1421. {
  1422. DebugPrintEx(
  1423. DEBUG_ERR,
  1424. TEXT("WideCharToMultiByte failed with %ld"),
  1425. GetLastError());
  1426. return FALSE;
  1427. }
  1428. return IsValidSubscriberIdA(szAnsiiSID);
  1429. } // IsValidSubscriberIdW
  1430. BOOL
  1431. IsValidSubscriberIdA (
  1432. LPCSTR lpcstrSubscriberId
  1433. )
  1434. {
  1435. DWORD dwLen;
  1436. DWORD dw;
  1437. DEBUG_FUNCTION_NAME(TEXT("IsValidSubscriberIdA"));
  1438. Assert (lpcstrSubscriberId);
  1439. dwLen = strlen (lpcstrSubscriberId);
  1440. if(dwLen > FXS_TSID_CSID_MAX_LENGTH)
  1441. {
  1442. return FALSE;
  1443. }
  1444. for (dw = 0; dw < dwLen; dw++)
  1445. {
  1446. if (!isprint (lpcstrSubscriberId[dw]))
  1447. {
  1448. DebugPrintEx(
  1449. DEBUG_ERR,
  1450. TEXT("%s contains invalid characters"),
  1451. lpcstrSubscriberId);
  1452. return FALSE;
  1453. }
  1454. }
  1455. return TRUE;
  1456. } // IsValidSubscriberIdA