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.

557 lines
15 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. /*****************************************************************************\
  17. * utlInternalValidatePrinterHandle
  18. *
  19. * Returns the port-handle if the specified printer-handle is a valid.
  20. *
  21. \*****************************************************************************/
  22. PCINETMONPORT utlInternalValidatePrinterHandle(
  23. HANDLE hPrinter,
  24. BOOL bAllowDeletePending,
  25. PBOOL pbDeletePending)
  26. {
  27. LPINET_HPRINTER pPrt;
  28. PCINETMONPORT pIniPort = NULL;
  29. if (pbDeletePending)
  30. *pbDeletePending = FALSE;
  31. _try {
  32. if ((pPrt = (LPINET_HPRINTER)hPrinter)) {
  33. if ((pPrt->dwSignature == IPO_SIGNATURE) &&
  34. !(pPrt->dwStatus & PP_ZOMBIE)) {
  35. pIniPort = (PCINETMONPORT) pPrt->hPort;
  36. if (pbDeletePending) {
  37. *pbDeletePending = pIniPort->bDeletePending();
  38. }
  39. if (!bAllowDeletePending) {
  40. if (pIniPort->bDeletePending()) {
  41. pIniPort = NULL;
  42. }
  43. }
  44. }
  45. }
  46. } _except(1) {
  47. pIniPort = NULL;
  48. }
  49. if (pIniPort == NULL) {
  50. DBG_MSG(DBG_LEV_ERROR, (TEXT("Call: utlValidatePrinterHandle: Invalid Handle: Handle(%08lX)"), hPrinter));
  51. SetLastError(ERROR_INVALID_HANDLE);
  52. }
  53. return pIniPort;
  54. }
  55. /*****************************************************************************\
  56. * utlValidatePrinterHandle
  57. *
  58. * Returns the port-handle if the specified printer-handle is a valid.
  59. *
  60. \*****************************************************************************/
  61. PCINETMONPORT utlValidatePrinterHandle(
  62. HANDLE hPrinter)
  63. {
  64. return utlInternalValidatePrinterHandle (hPrinter, FALSE, NULL);
  65. }
  66. /*****************************************************************************\
  67. * utlValidatePrinterHandleForClose
  68. *
  69. * Returns the port-handle if the specified printer-handle is a valid.
  70. *
  71. \*****************************************************************************/
  72. PCINETMONPORT utlValidatePrinterHandleForClose(
  73. HANDLE hPrinter,
  74. PBOOL pbDeletePending)
  75. {
  76. return utlInternalValidatePrinterHandle (hPrinter, TRUE, pbDeletePending);
  77. }
  78. /*****************************************************************************\
  79. * utlValidateXcvPrinterHandle
  80. *
  81. * Returns the port-handle if the specified printer-handle is a valid.
  82. *
  83. \*****************************************************************************/
  84. LPTSTR utlValidateXcvPrinterHandle(
  85. HANDLE hPrinter)
  86. {
  87. LPINET_XCV_HPRINTER pPrt;
  88. LPTSTR lpszPortName = NULL;
  89. _try {
  90. if ((pPrt = (LPINET_XCV_HPRINTER)hPrinter)) {
  91. if ((pPrt->dwSignature == IPO_XCV_SIGNATURE)) {
  92. lpszPortName = pPrt->lpszName;
  93. }
  94. }
  95. } _except(1) {
  96. lpszPortName = NULL;
  97. }
  98. if (lpszPortName == NULL) {
  99. DBG_MSG(DBG_LEV_ERROR, (TEXT("Call: utlValidateXcvPrinterHandle: Invalid Handle: Handle(%08lX)"), hPrinter));
  100. SetLastError(ERROR_INVALID_HANDLE);
  101. }
  102. return lpszPortName;
  103. }
  104. /********************************************************************************
  105. Name:
  106. EncodeUnicodePrinterName
  107. Description:
  108. Encode the printer name to avoid special characters, also encode any chars
  109. with ASC code between 0x80 and 0xffff. This is to avoid the conversion betwwen
  110. different codepages when the client and the server have different language
  111. packages.
  112. The difference between this function and EncodePrinterName in Spllib is that
  113. this function does not encode ' ', '$' and other special ANSI characters.
  114. Arguments:
  115. lpText: the normal text string
  116. lpHTMLStr: the buf provided by the caller to store the encoded string
  117. if it is NULL, the function will return a FALSE
  118. lpdwSize: Pointer to the size of the buffer (in characters)
  119. Return Value:
  120. If the function succeeds, the return value is TRUE;
  121. If the function fails, the return value is FALSE. To get extended error
  122. information, call GetLastError.
  123. ********************************************************************************/
  124. BOOL EncodeUnicodePrinterName (LPCTSTR lpText, LPTSTR lpHTMLStr, LPDWORD lpdwSize)
  125. {
  126. #define MAXLEN_PER_CHAR 6
  127. #define BIN2ASC(bCode,lpHTMLStr) *lpHTMLStr++ = HexToAsc ((bCode) >> 4);\
  128. *lpHTMLStr++ = HexToAsc ((bCode) & 0xf)
  129. DWORD dwLen;
  130. BYTE bCode;
  131. if (!lpText || !lpdwSize) {
  132. SetLastError (ERROR_INVALID_DATA);
  133. return FALSE;
  134. }
  135. dwLen = MAXLEN_PER_CHAR * lstrlen (lpText) + 1;
  136. if (!lpHTMLStr || *lpdwSize < dwLen) {
  137. SetLastError (ERROR_INSUFFICIENT_BUFFER);
  138. *lpdwSize = dwLen;
  139. return FALSE;
  140. }
  141. while (*lpText) {
  142. if ((DWORD) (*lpText) > 0xff ) {
  143. // Encode as ~0hhll hh is the high byte, ll is the low byte
  144. *lpHTMLStr++ = TEXT ('~');
  145. *lpHTMLStr++ = TEXT ('0');
  146. // Get the high byte
  147. bCode = (*lpText & 0xff00) >> 8;
  148. BIN2ASC(bCode,lpHTMLStr);
  149. // Get the low byte
  150. bCode = (*lpText & 0xff);
  151. BIN2ASC(bCode,lpHTMLStr);
  152. }
  153. else if ((DWORD) (*lpText) > 0x7f) {
  154. // Encode as ~xx
  155. *lpHTMLStr++ = TEXT ('~');
  156. bCode = *lpText & 0xff;
  157. BIN2ASC(bCode,lpHTMLStr);
  158. }
  159. else {
  160. *lpHTMLStr++ = *lpText;
  161. }
  162. lpText++;
  163. }
  164. *lpHTMLStr = NULL;
  165. return TRUE;
  166. }
  167. /*****************************************************************************\
  168. * utlParseHostShare
  169. *
  170. * Parses the PortName (http://host[:port][/][/share]) into its
  171. * post/Share/Port components.
  172. *
  173. * We accept six formats
  174. * 1. http://server
  175. * 2. http://server:port
  176. * 3. http://server/
  177. * 4. http://server:port/
  178. * 5. http://server/share
  179. * 6. http://server:port/share
  180. *
  181. * This routine returns allocated pointers that must be freed by the caller.
  182. *
  183. \*****************************************************************************/
  184. BOOL utlParseHostShare(
  185. LPCTSTR lpszPortName,
  186. LPTSTR *lpszHost,
  187. LPTSTR *lpszShare,
  188. LPINTERNET_PORT lpPort,
  189. LPBOOL lpbHTTPS)
  190. {
  191. LPTSTR lpszPrt;
  192. LPTSTR lpszTmp;
  193. LPTSTR lpszPos;
  194. BOOL bRet = FALSE;
  195. // Initialize the return buffers to NULL.
  196. //
  197. *lpszHost = NULL;
  198. *lpszShare = NULL;
  199. *lpPort = 0;
  200. // Parse the host-name and the share name. The pszPortName is
  201. // currently in the format of http://host[:portnumber]/share. We will parse
  202. // this from left->right since the share-name can be a path (we
  203. // wouldn't really know the exact length). However, we do know the
  204. // location for the host-name, and anything after that should be
  205. // the share-name.
  206. //
  207. // First find the ':'. The host-name should begin two "//" after
  208. // that.
  209. //
  210. if (lpszPrt = memAllocStr(lpszPortName)) {
  211. static TCHAR szHttp[] = TEXT ("http://");
  212. static TCHAR szHttps[] = TEXT ("https://");
  213. lpszTmp = NULL;
  214. if (!_tcsnicmp (lpszPrt, szHttp, COUNTOF (szHttp) - 1)) {
  215. lpszTmp = lpszPrt + COUNTOF (szHttp) - 1;
  216. *lpbHTTPS = FALSE;
  217. }
  218. else if (!_tcsnicmp (lpszPrt, szHttps, COUNTOF (szHttps) - 1)) {
  219. lpszTmp = lpszPrt + COUNTOF (szHttps) - 1;
  220. *lpbHTTPS = TRUE;
  221. }
  222. if (lpszTmp) {
  223. lpszPos = utlStrChr(lpszTmp, TEXT(':'));
  224. if (lpszPos) {
  225. //This url has a port number, we need to parse it
  226. *lpszPos++ = 0;
  227. *lpszHost = memAllocStr(lpszTmp);
  228. *lpPort = (INTERNET_PORT) _ttol (lpszPos);
  229. lpszTmp = lpszPos;
  230. if (lpszPos = utlStrChr(lpszTmp, TEXT('/'))) {
  231. *lpszShare = memAllocStr(++lpszPos);
  232. }
  233. else {
  234. *lpszShare = memAllocStr(TEXT (""));
  235. }
  236. }
  237. else {
  238. // Use the default port number: 80
  239. if (lpszPos = utlStrChr(lpszTmp, TEXT('/'))) {
  240. *lpszPos++ = TEXT('\0');
  241. *lpszHost = memAllocStr(lpszTmp);
  242. *lpszShare = memAllocStr(lpszPos);
  243. }
  244. else {
  245. // The whole thing is a host name
  246. *lpszHost = memAllocStr(lpszTmp);
  247. *lpszShare = memAllocStr(TEXT (""));
  248. }
  249. }
  250. if (*lpszShare) {
  251. //
  252. // Let's check if we need to encode the share name
  253. //
  254. INT iMode = IS_TEXT_UNICODE_ASCII16;
  255. if (IsTextUnicode ((LPVOID) *lpszShare, lstrlen (*lpszShare) * sizeof (WCHAR), &iMode) == 0) {
  256. // The text string is a unicode string contains non-ASCII characters
  257. // We need to encode the URL into ansi strings
  258. DWORD dwSize;
  259. BOOL bConversion = FALSE;
  260. LPWSTR pszEncodedName = NULL;
  261. EncodeUnicodePrinterName (*lpszShare, NULL, &dwSize);
  262. if ((pszEncodedName = (LPWSTR) memAlloc (sizeof (WCHAR) * dwSize))) {
  263. if (EncodeUnicodePrinterName (*lpszShare, pszEncodedName, &dwSize)) {
  264. memFreeStr (*lpszShare);
  265. *lpszShare = pszEncodedName;
  266. bConversion = TRUE;
  267. }
  268. }
  269. if (!bConversion) {
  270. memFreeStr (pszEncodedName);
  271. memFreeStr (*lpszShare);
  272. *lpszShare = NULL;
  273. }
  274. }
  275. }
  276. if (*lpszHost && *lpszShare) {
  277. bRet = TRUE;
  278. } else {
  279. // Don't worry that we could be freeing a NULL pointer.
  280. // The mem-routines check this.
  281. //
  282. memFreeStr(*lpszHost);
  283. memFreeStr(*lpszShare);
  284. *lpszHost = NULL;
  285. *lpszShare = NULL;
  286. }
  287. }
  288. memFreeStr(lpszPrt);
  289. }
  290. return bRet;
  291. }
  292. /*****************************************************************************\
  293. * utlStrChr
  294. *
  295. * Looks for the first location where (c) resides.
  296. *
  297. \*****************************************************************************/
  298. LPTSTR utlStrChr(
  299. LPCTSTR cs,
  300. TCHAR c)
  301. {
  302. while (*cs != TEXT('\0')) {
  303. if (*cs == c)
  304. return (LPTSTR)cs;
  305. cs++;
  306. }
  307. // Fail to find c in cs.
  308. //
  309. return NULL;
  310. }
  311. /*****************************************************************************\
  312. * utlStrChrR
  313. *
  314. * Looks for first occurrence of (c) starting from the end of the buffer.
  315. *
  316. \*****************************************************************************/
  317. LPTSTR utlStrChrR(
  318. LPCTSTR cs,
  319. TCHAR c)
  320. {
  321. LPTSTR ct;
  322. ct = (LPTSTR)cs + (lstrlen(cs) - 1);
  323. while (ct >= cs) {
  324. if (*ct == c)
  325. return ct;
  326. ct--;
  327. }
  328. // Fail to find c in cs.
  329. //
  330. return NULL;
  331. }
  332. /*****************************************************************************\
  333. * utlPackStrings
  334. *
  335. * This routine is called after the buffer size is calculated for all the
  336. * strings returned in the packed structure.
  337. *
  338. \*****************************************************************************/
  339. LPBYTE utlPackStrings(
  340. LPTSTR *pSource,
  341. LPBYTE pDest,
  342. LPDWORD pDestOffsets,
  343. LPBYTE pEnd)
  344. {
  345. while (*pDestOffsets != (DWORD)-1) {
  346. if (*pSource) {
  347. size_t uSize = lstrlen(*pSource) + 1;
  348. pEnd -= (uSize * sizeof(TCHAR));
  349. StringCchCopy((LPTSTR)pEnd, uSize, *pSource);
  350. *(LPTSTR *)(pDest + *pDestOffsets) = (LPTSTR)pEnd;
  351. } else {
  352. *(LPTSTR *)(pDest + *pDestOffsets) = TEXT('\0');
  353. }
  354. pSource++;
  355. pDestOffsets++;
  356. }
  357. return pEnd;
  358. }
  359. /*****************************************************************************\
  360. * utlStrSize
  361. *
  362. * Returns the number of bytes needed to store a string including the NULL
  363. * terminator.
  364. *
  365. \*****************************************************************************/
  366. int utlStrSize(
  367. LPCTSTR lpszStr)
  368. {
  369. return (lpszStr ? ((lstrlen(lpszStr) + 1) * sizeof(TCHAR)) : 0);
  370. }
  371. BOOL
  372. MyName(
  373. PCTSTR pName
  374. )
  375. {
  376. DWORD dwIndex = 0;
  377. if (!pName || !*pName)
  378. return TRUE;
  379. if (*pName == L'\\' && *(pName+1) == L'\\') {
  380. if (!lstrcmpi(pName, g_szMachine + 2))
  381. return TRUE;
  382. return CacheIsNameInNodeList(g_szMachine, pName + 2) == S_OK;
  383. }
  384. SetLastError(ERROR_INVALID_NAME);
  385. return FALSE;
  386. }
  387. /*****************************************************************************\
  388. * GetUserName
  389. *
  390. * Retrieves the username for the current logged on thread.
  391. *
  392. \*****************************************************************************/
  393. LPTSTR
  394. GetUserName(VOID)
  395. {
  396. DWORD cbSize;
  397. LPTSTR lpszUser;
  398. // Initialize the count and retrieve the number of characters
  399. // necessary for the username.
  400. //
  401. cbSize = 0;
  402. GetUserName(NULL, &cbSize);
  403. // If we were not able to retrieve a valid-count, then allocate
  404. // an empty string to return from this call.
  405. //
  406. if (cbSize) {
  407. if (lpszUser = (LPTSTR)memAlloc(cbSize * sizeof(TCHAR))) {
  408. if (GetUserName(lpszUser, &cbSize) == FALSE) {
  409. *lpszUser = TEXT('\0');
  410. goto log_error;
  411. }
  412. } else {
  413. DBG_MSG(DBG_LEV_ERROR, (TEXT("Err : GetUserName : Out of memory")));
  414. }
  415. } else {
  416. lpszUser = memAllocStr(TEXT("Unknown"));
  417. log_error:
  418. DBG_MSG(DBG_LEV_ERROR, (TEXT("Err : GetUserName Failed %d"), GetLastError()));
  419. SetLastError(ERROR_OUTOFMEMORY);
  420. }
  421. return lpszUser;
  422. }
  423. VOID
  424. EndBrowserSession (
  425. VOID)
  426. {
  427. g_pcsEndBrowserSessionLock->Lock();
  428. InetInternetSetOption(NULL, INTERNET_OPTION_END_BROWSER_SESSION, NULL, 0);
  429. g_pcsEndBrowserSessionLock->Unlock();
  430. }