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.

697 lines
17 KiB

  1. /*****************************************************************************\
  2. * MODULE: util.c
  3. *
  4. * This module contains utility routines.
  5. *
  6. *
  7. * Copyright (C) 1996-1997 Microsoft Corporation
  8. * Copyright (C) 1996-1997 Hewlett Packard
  9. *
  10. * History:
  11. * 07-Oct-1996 HWP-Guys Initiated port from win95 to winNT
  12. *
  13. \*****************************************************************************/
  14. #include "precomp.h"
  15. #include "priv.h"
  16. #ifdef NOT_IMPLEMENTED
  17. // NOTE: The shell-extensions don't seem to be necessary at the moment.
  18. //
  19. // 15-Oct-1996 : ChrisWil
  20. //
  21. int APIENTRY ShexDllMain(
  22. HINSTANCE hInstance,
  23. DWORD dwReason,
  24. LPVOID lpReserved);
  25. #endif
  26. /*****************************************************************************\
  27. * utlInternalValidatePrinterHandle
  28. *
  29. * Returns the port-handle if the specified printer-handle is a valid.
  30. *
  31. \*****************************************************************************/
  32. PCINETMONPORT utlInternalValidatePrinterHandle(
  33. HANDLE hPrinter,
  34. BOOL bAllowDeletePending,
  35. PBOOL pbDeletePending)
  36. {
  37. LPINET_HPRINTER pPrt;
  38. PCINETMONPORT pIniPort = NULL;
  39. if (pbDeletePending)
  40. *pbDeletePending = FALSE;
  41. _try {
  42. if ((pPrt = (LPINET_HPRINTER)hPrinter)) {
  43. if ((pPrt->dwSignature == IPO_SIGNATURE) &&
  44. !(pPrt->dwStatus & PP_ZOMBIE)) {
  45. pIniPort = (PCINETMONPORT) pPrt->hPort;
  46. if (pbDeletePending) {
  47. *pbDeletePending = pIniPort->bDeletePending();
  48. }
  49. if (!bAllowDeletePending) {
  50. if (pIniPort->bDeletePending()) {
  51. pIniPort = NULL;
  52. }
  53. }
  54. }
  55. }
  56. } _except(1) {
  57. pIniPort = NULL;
  58. }
  59. if (pIniPort == NULL) {
  60. DBG_MSG(DBG_LEV_ERROR, (TEXT("Call: utlValidatePrinterHandle: Invalid Handle: Handle(%08lX)"), hPrinter));
  61. SetLastError(ERROR_INVALID_HANDLE);
  62. }
  63. return pIniPort;
  64. }
  65. /*****************************************************************************\
  66. * utlValidatePrinterHandle
  67. *
  68. * Returns the port-handle if the specified printer-handle is a valid.
  69. *
  70. \*****************************************************************************/
  71. PCINETMONPORT utlValidatePrinterHandle(
  72. HANDLE hPrinter)
  73. {
  74. return utlInternalValidatePrinterHandle (hPrinter, FALSE, NULL);
  75. }
  76. /*****************************************************************************\
  77. * utlValidatePrinterHandleForClose
  78. *
  79. * Returns the port-handle if the specified printer-handle is a valid.
  80. *
  81. \*****************************************************************************/
  82. PCINETMONPORT utlValidatePrinterHandleForClose(
  83. HANDLE hPrinter,
  84. PBOOL pbDeletePending)
  85. {
  86. return utlInternalValidatePrinterHandle (hPrinter, TRUE, pbDeletePending);
  87. }
  88. #ifdef WINNT32
  89. /*****************************************************************************\
  90. * utlValidateXcvPrinterHandle
  91. *
  92. * Returns the port-handle if the specified printer-handle is a valid.
  93. *
  94. \*****************************************************************************/
  95. LPTSTR utlValidateXcvPrinterHandle(
  96. HANDLE hPrinter)
  97. {
  98. LPINET_XCV_HPRINTER pPrt;
  99. LPTSTR lpszPortName = NULL;
  100. _try {
  101. if ((pPrt = (LPINET_XCV_HPRINTER)hPrinter)) {
  102. if ((pPrt->dwSignature == IPO_XCV_SIGNATURE)) {
  103. lpszPortName = pPrt->lpszName;
  104. }
  105. }
  106. } _except(1) {
  107. lpszPortName = NULL;
  108. }
  109. if (lpszPortName == NULL) {
  110. DBG_MSG(DBG_LEV_ERROR, (TEXT("Call: utlValidateXcvPrinterHandle: Invalid Handle: Handle(%08lX)"), hPrinter));
  111. SetLastError(ERROR_INVALID_HANDLE);
  112. }
  113. return lpszPortName;
  114. }
  115. #endif
  116. /********************************************************************************
  117. Name:
  118. EncodeUnicodePrinterName
  119. Description:
  120. Encode the printer name to avoid special characters, also encode any chars
  121. with ASC code between 0x80 and 0xffff. This is to avoid the conversion betwwen
  122. different codepages when the client and the server have different language
  123. packages.
  124. The difference between this function and EncodePrinterName in Spllib is that
  125. this function does not encode ' ', '$' and other special ANSI characters.
  126. Arguments:
  127. lpText: the normal text string
  128. lpHTMLStr: the buf provided by the caller to store the encoded string
  129. if it is NULL, the function will return a FALSE
  130. lpdwSize: Pointer to the size of the buffer (in characters)
  131. Return Value:
  132. If the function succeeds, the return value is TRUE;
  133. If the function fails, the return value is FALSE. To get extended error
  134. information, call GetLastError.
  135. ********************************************************************************/
  136. BOOL EncodeUnicodePrinterName (LPCTSTR lpText, LPTSTR lpHTMLStr, LPDWORD lpdwSize)
  137. {
  138. #define MAXLEN_PER_CHAR 6
  139. #define BIN2ASC(bCode,lpHTMLStr) *lpHTMLStr++ = HexToAsc ((bCode) >> 4);\
  140. *lpHTMLStr++ = HexToAsc ((bCode) & 0xf)
  141. DWORD dwLen;
  142. BYTE bCode;
  143. if (!lpText || !lpdwSize) {
  144. SetLastError (ERROR_INVALID_DATA);
  145. return FALSE;
  146. }
  147. dwLen = MAXLEN_PER_CHAR * lstrlen (lpText) + 1;
  148. if (!lpHTMLStr || *lpdwSize < dwLen) {
  149. SetLastError (ERROR_INSUFFICIENT_BUFFER);
  150. *lpdwSize = dwLen;
  151. return FALSE;
  152. }
  153. while (*lpText) {
  154. if ((DWORD) (*lpText) > 0xff ) {
  155. // Encode as ~0hhll hh is the high byte, ll is the low byte
  156. *lpHTMLStr++ = TEXT ('~');
  157. *lpHTMLStr++ = TEXT ('0');
  158. // Get the high byte
  159. bCode = (*lpText & 0xff00) >> 8;
  160. BIN2ASC(bCode,lpHTMLStr);
  161. // Get the low byte
  162. bCode = (*lpText & 0xff);
  163. BIN2ASC(bCode,lpHTMLStr);
  164. }
  165. else if ((DWORD) (*lpText) > 0x7f) {
  166. // Encode as ~xx
  167. *lpHTMLStr++ = TEXT ('~');
  168. bCode = *lpText & 0xff;
  169. BIN2ASC(bCode,lpHTMLStr);
  170. }
  171. else {
  172. *lpHTMLStr++ = *lpText;
  173. }
  174. lpText++;
  175. }
  176. *lpHTMLStr = NULL;
  177. return TRUE;
  178. }
  179. /*****************************************************************************\
  180. * utlParseHostShare
  181. *
  182. * Parses the PortName (http://host[:port][/][/share]) into its
  183. * post/Share/Port components.
  184. *
  185. * We accept six formats
  186. * 1. http://server
  187. * 2. http://server:port
  188. * 3. http://server/
  189. * 4. http://server:port/
  190. * 5. http://server/share
  191. * 6. http://server:port/share
  192. *
  193. * This routine returns allocated pointers that must be freed by the caller.
  194. *
  195. \*****************************************************************************/
  196. BOOL utlParseHostShare(
  197. LPCTSTR lpszPortName,
  198. LPTSTR *lpszHost,
  199. LPTSTR *lpszShare,
  200. LPINTERNET_PORT lpPort,
  201. LPBOOL lpbHTTPS)
  202. {
  203. LPTSTR lpszPrt;
  204. LPTSTR lpszTmp;
  205. LPTSTR lpszPos;
  206. BOOL bRet = FALSE;
  207. // Initialize the return buffers to NULL.
  208. //
  209. *lpszHost = NULL;
  210. *lpszShare = NULL;
  211. *lpPort = 0;
  212. // Parse the host-name and the share name. The pszPortName is
  213. // currently in the format of http://host[:portnumber]/share. We will parse
  214. // this from left->right since the share-name can be a path (we
  215. // wouldn't really know the exact length). However, we do know the
  216. // location for the host-name, and anything after that should be
  217. // the share-name.
  218. //
  219. // First find the ':'. The host-name should begin two "//" after
  220. // that.
  221. //
  222. if (lpszPrt = memAllocStr(lpszPortName)) {
  223. static TCHAR szHttp[] = TEXT ("http://");
  224. static TCHAR szHttps[] = TEXT ("https://");
  225. lpszTmp = NULL;
  226. if (!_tcsnicmp (lpszPrt, szHttp, COUNTOF (szHttp) - 1)) {
  227. lpszTmp = lpszPrt + COUNTOF (szHttp) - 1;
  228. *lpbHTTPS = FALSE;
  229. }
  230. else if (!_tcsnicmp (lpszPrt, szHttps, COUNTOF (szHttps) - 1)) {
  231. lpszTmp = lpszPrt + COUNTOF (szHttps) - 1;
  232. *lpbHTTPS = TRUE;
  233. }
  234. if (lpszTmp) {
  235. lpszPos = utlStrChr(lpszTmp, TEXT(':'));
  236. if (lpszPos) {
  237. //This url has a port number, we need to parse it
  238. *lpszPos++ = 0;
  239. *lpszHost = memAllocStr(lpszTmp);
  240. *lpPort = (INTERNET_PORT) _ttol (lpszPos);
  241. lpszTmp = lpszPos;
  242. if (lpszPos = utlStrChr(lpszTmp, TEXT('/'))) {
  243. *lpszShare = memAllocStr(++lpszPos);
  244. }
  245. else {
  246. *lpszShare = memAllocStr(TEXT (""));
  247. }
  248. }
  249. else {
  250. // Use the default port number: 80
  251. if (lpszPos = utlStrChr(lpszTmp, TEXT('/'))) {
  252. *lpszPos++ = TEXT('\0');
  253. *lpszHost = memAllocStr(lpszTmp);
  254. *lpszShare = memAllocStr(lpszPos);
  255. }
  256. else {
  257. // The whole thing is a host name
  258. *lpszHost = memAllocStr(lpszTmp);
  259. *lpszShare = memAllocStr(TEXT (""));
  260. }
  261. }
  262. #ifdef WINNT32
  263. if (*lpszShare) {
  264. //
  265. // Let's check if we need to encode the share name
  266. //
  267. INT iMode = IS_TEXT_UNICODE_ASCII16;
  268. if (IsTextUnicode ((LPVOID) *lpszShare, lstrlen (*lpszShare) * sizeof (WCHAR), &iMode) == 0) {
  269. // The text string is a unicode string contains non-ASCII characters
  270. // We need to encode the URL into ansi strings
  271. DWORD dwSize;
  272. BOOL bConversion = FALSE;
  273. LPWSTR pszEncodedName = NULL;
  274. EncodeUnicodePrinterName (*lpszShare, NULL, &dwSize);
  275. if ((pszEncodedName = (LPWSTR) memAlloc (sizeof (WCHAR) * dwSize))) {
  276. if (EncodeUnicodePrinterName (*lpszShare, pszEncodedName, &dwSize)) {
  277. memFreeStr (*lpszShare);
  278. *lpszShare = pszEncodedName;
  279. bConversion = TRUE;
  280. }
  281. }
  282. if (!bConversion) {
  283. memFreeStr (pszEncodedName);
  284. memFreeStr (*lpszShare);
  285. *lpszShare = NULL;
  286. }
  287. }
  288. }
  289. #endif
  290. if (*lpszHost && *lpszShare) {
  291. bRet = TRUE;
  292. } else {
  293. // Don't worry that we could be freeing a NULL pointer.
  294. // The mem-routines check this.
  295. //
  296. memFreeStr(*lpszHost);
  297. memFreeStr(*lpszShare);
  298. *lpszHost = NULL;
  299. *lpszShare = NULL;
  300. }
  301. }
  302. memFreeStr(lpszPrt);
  303. }
  304. return bRet;
  305. }
  306. /*****************************************************************************\
  307. * utlStrChr
  308. *
  309. * Looks for the first location where (c) resides.
  310. *
  311. \*****************************************************************************/
  312. LPTSTR utlStrChr(
  313. LPCTSTR cs,
  314. TCHAR c)
  315. {
  316. while (*cs != TEXT('\0')) {
  317. if (*cs == c)
  318. return (LPTSTR)cs;
  319. cs++;
  320. }
  321. // Fail to find c in cs.
  322. //
  323. return NULL;
  324. }
  325. /*****************************************************************************\
  326. * utlStrChrR
  327. *
  328. * Looks for first occurrence of (c) starting from the end of the buffer.
  329. *
  330. \*****************************************************************************/
  331. LPTSTR utlStrChrR(
  332. LPCTSTR cs,
  333. TCHAR c)
  334. {
  335. LPTSTR ct;
  336. ct = (LPTSTR)cs + (lstrlen(cs) - 1);
  337. while (ct >= cs) {
  338. if (*ct == c)
  339. return ct;
  340. ct--;
  341. }
  342. // Fail to find c in cs.
  343. //
  344. return NULL;
  345. }
  346. /*****************************************************************************\
  347. * utlPackStrings
  348. *
  349. *
  350. \*****************************************************************************/
  351. LPBYTE utlPackStrings(
  352. LPTSTR *pSource,
  353. LPBYTE pDest,
  354. LPDWORD pDestOffsets,
  355. LPBYTE pEnd)
  356. {
  357. while (*pDestOffsets != (DWORD)-1) {
  358. if (*pSource) {
  359. pEnd -= (lstrlen(*pSource) * sizeof(TCHAR)) + sizeof(TCHAR);
  360. *(LPTSTR *)(pDest + *pDestOffsets) = lstrcpy((LPTSTR)pEnd, *pSource);
  361. } else {
  362. *(LPTSTR *)(pDest + *pDestOffsets) = TEXT('\0');
  363. }
  364. pSource++;
  365. pDestOffsets++;
  366. }
  367. return pEnd;
  368. }
  369. /*****************************************************************************\
  370. * utlStrSize
  371. *
  372. * Returns the number of bytes needed to store a string including the NULL
  373. * terminator.
  374. *
  375. \*****************************************************************************/
  376. int utlStrSize(
  377. LPCTSTR lpszStr)
  378. {
  379. return (lpszStr ? ((lstrlen(lpszStr) + 1) * sizeof(TCHAR)) : 0);
  380. }
  381. /*****************************************************************************\
  382. * utlRegGetVal
  383. *
  384. * Retrieves the registry-value for the specified key.
  385. *
  386. \*****************************************************************************/
  387. LPTSTR utlRegGetVal(
  388. HKEY hKey,
  389. LPCTSTR lpszKey)
  390. {
  391. DWORD dwType;
  392. DWORD cbSize;
  393. LONG lRet;
  394. LPTSTR lpszStr;
  395. dwType = 0;
  396. cbSize = 0;
  397. lRet = RegQueryValueEx(hKey, lpszKey, NULL, &dwType, NULL, &cbSize);
  398. if (lRet == ERROR_SUCCESS && cbSize > 0) {
  399. if (lpszStr = (LPTSTR)memAlloc(cbSize)) {
  400. lRet = RegQueryValueEx(hKey, lpszKey, NULL, &dwType, (LPBYTE)lpszStr, &cbSize);
  401. if (lRet == ERROR_SUCCESS)
  402. return lpszStr;
  403. memFreeStr(lpszStr);
  404. }
  405. }
  406. return NULL;
  407. }
  408. #ifdef WINNT32
  409. /*++
  410. Routine Description
  411. Determines whether or not a machine name contains the local machine name.
  412. Localspl enum calls fail if pName != local machine name (\\Machine).
  413. Remote enum provider is then called. The remote enum provider must check
  414. if the UNC name refers to the local machine, and fail if it does to avoid
  415. endless recursion.
  416. Arguments:
  417. LPWSTR pName - UNC name.
  418. Return Value:
  419. TRUE: pName == \\szMachineName\...
  420. - or -
  421. pName == \\szMachineName
  422. FALSE: anything else
  423. Author: swilson
  424. --*/
  425. BOOL
  426. MyUNCName(
  427. LPTSTR pNameStart
  428. )
  429. {
  430. LPTSTR pMachine = g_szMachine;
  431. LPTSTR pName;
  432. DWORD i;
  433. if (!pNameStart || !*pNameStart) // This differs from MyName(), which returns TRUE
  434. return FALSE;
  435. if (*pNameStart == L'\\' && *(pNameStart + 1) == L'\\') {
  436. for (i = 0 , pName = pNameStart + 2 ; i < g_cOtherNames ; ++i , pName = pNameStart + 2) {
  437. for(pMachine = g_ppszOtherNames[i] ;
  438. *pName && towupper(*pName) == towupper(*pMachine) ;
  439. ++pName, ++pMachine)
  440. ;
  441. if(!*pMachine && (!*pName || *pName == L'\\'))
  442. return TRUE;
  443. }
  444. }
  445. return FALSE;
  446. }
  447. BOOL MyName(
  448. LPCTSTR pName)
  449. {
  450. DWORD dwIndex = 0;
  451. if (!pName || !*pName)
  452. return TRUE;
  453. if (*pName == L'\\' && *(pName+1) == L'\\') {
  454. if (!lstrcmpi(pName, g_szMachine))
  455. return TRUE;
  456. while ( dwIndex < g_cOtherNames ) {
  457. if ( !lstrcmpi(pName+2, g_ppszOtherNames[dwIndex]) )
  458. return TRUE;
  459. ++dwIndex;
  460. }
  461. }
  462. SetLastError( ERROR_INVALID_NAME );
  463. return FALSE;
  464. }
  465. #endif
  466. BOOL MyServer(
  467. LPCTSTR pName)
  468. {
  469. DWORD dwIndex = 0;
  470. if (!pName || !*pName)
  471. return FALSE;
  472. if (!lstrcmpi(pName, g_szMachine))
  473. return TRUE;
  474. if (!lstrcmpi(pName, TEXT ("localhost")))
  475. return TRUE;
  476. #ifdef WINNT32
  477. while ( dwIndex < g_cOtherNames ) {
  478. if ( !lstrcmpi(pName, g_ppszOtherNames[dwIndex]) )
  479. return TRUE;
  480. ++dwIndex;
  481. }
  482. #endif
  483. SetLastError( ERROR_INVALID_NAME );
  484. return FALSE;
  485. }
  486. /*****************************************************************************\
  487. * GetUserName
  488. *
  489. * Retrieves the username for the current logged on thread.
  490. *
  491. \*****************************************************************************/
  492. LPTSTR
  493. GetUserName(VOID)
  494. {
  495. DWORD cbSize;
  496. LPTSTR lpszUser;
  497. // Initialize the count and retrieve the number of characters
  498. // necessary for the username.
  499. //
  500. cbSize = 0;
  501. GetUserName(NULL, &cbSize);
  502. // If we were not able to retrieve a valid-count, then allocate
  503. // an empty string to return from this call.
  504. //
  505. if (cbSize) {
  506. if (lpszUser = (LPTSTR)memAlloc(cbSize * sizeof(TCHAR))) {
  507. if (GetUserName(lpszUser, &cbSize) == FALSE) {
  508. *lpszUser = TEXT('\0');
  509. goto log_error;
  510. }
  511. } else {
  512. DBG_MSG(DBG_LEV_ERROR, (TEXT("Err : GetUserName : Out of memory")));
  513. }
  514. } else {
  515. lpszUser = memAllocStr(TEXT("Unknown"));
  516. log_error:
  517. DBG_MSG(DBG_LEV_ERROR, (TEXT("Err : GetUserName Failed %d"), GetLastError()));
  518. SetLastError(ERROR_OUTOFMEMORY);
  519. }
  520. return lpszUser;
  521. }
  522. VOID
  523. EndBrowserSession (
  524. VOID)
  525. {
  526. g_pcsEndBrowserSessionLock->Lock();
  527. InetInternetSetOption(NULL, INTERNET_OPTION_END_BROWSER_SESSION, NULL, 0);
  528. g_pcsEndBrowserSessionLock->Unlock();
  529. }