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.

824 lines
25 KiB

  1. /*****************************************************************************\
  2. * MODULE: msw3prt.cxx
  3. *
  4. * The module contains routines to implement the ISAPI interface.
  5. *
  6. * PURPOSE Windows HTTP/HTML printer interface
  7. *
  8. * Copyright (C) 1996-1997 Microsoft Corporation
  9. *
  10. * History:
  11. * 01/16/96 eriksn Created based on ISAPI sample DLL
  12. * 07/15/96 babakj Ported to NT
  13. * 02/04/97 weihaic Enabled Unicode mode
  14. *
  15. \*****************************************************************************/
  16. #include "pch.h"
  17. /*****************************************************************************\
  18. * GetClientInfo
  19. *
  20. * Returns a DWORD representation of the client architecture/ver information.
  21. *
  22. \*****************************************************************************/
  23. DWORD GetClientInfo(
  24. PALLINFO pAllInfo)
  25. {
  26. DWORD dwCliInfo = 0;
  27. LPSTR lpszPtr;
  28. if (pAllInfo->pECB->cbAvailable)
  29. {
  30. //
  31. // First Allocate a new buffer on the heap to hold the input string
  32. //
  33. lpszPtr = (LPSTR) LocalAlloc(LPTR, (pAllInfo->pECB->cbAvailable+1));
  34. if (lpszPtr)
  35. {
  36. //
  37. // Copy the memory over and then null terminate past the message
  38. //
  39. memcpy( lpszPtr, pAllInfo->pECB->lpbData, pAllInfo->pECB->cbAvailable);
  40. lpszPtr[pAllInfo->pECB->cbAvailable] = 0x00;
  41. while (*lpszPtr && (*lpszPtr != '='))
  42. lpszPtr++;
  43. if (*lpszPtr)
  44. dwCliInfo = atoi(++lpszPtr);
  45. LocalFree(lpszPtr);
  46. }
  47. }
  48. else
  49. {
  50. if (lpszPtr = pAllInfo->pECB->lpszQueryString)
  51. {
  52. while (*lpszPtr && (*lpszPtr != '&'))
  53. lpszPtr++;
  54. if (*lpszPtr)
  55. dwCliInfo = atoi(++lpszPtr);
  56. }
  57. }
  58. return dwCliInfo;
  59. }
  60. /*****************************************************************************\
  61. * GetIppReq
  62. *
  63. * Returns the request-type of the IPP-stream.
  64. *
  65. \*****************************************************************************/
  66. WORD GetIppReq(
  67. PALLINFO pAllInfo)
  68. {
  69. LPWORD pwPtr;
  70. WORD wValue = 0;
  71. if (pAllInfo->pECB->cbAvailable >= sizeof(DWORD)) {
  72. if (pwPtr = (LPWORD)pAllInfo->pECB->lpbData) {
  73. CopyMemory (&wValue, pwPtr + 1, sizeof (WORD));
  74. return ntohs(wValue);
  75. }
  76. }
  77. return 0;
  78. }
  79. /*****************************************************************************\
  80. * IsSecureReq
  81. *
  82. * Returns whether the request comes from a secure https channel.
  83. *
  84. \*****************************************************************************/
  85. BOOL IsSecureReq(
  86. EXTENSION_CONTROL_BLOCK *pECB)
  87. {
  88. BOOL bRet;
  89. DWORD cbBuf;
  90. CHAR szBuf[10];
  91. cbBuf = 10;
  92. bRet = pECB->GetServerVariable(pECB->ConnID,
  93. "HTTPS",
  94. &szBuf,
  95. &cbBuf);
  96. if (bRet && (cbBuf <= 4)) {
  97. if (lstrcmpiA(szBuf, "on") == 0)
  98. return TRUE;
  99. }
  100. return FALSE;
  101. }
  102. /*****************************************************************************\
  103. * GetPrinterName
  104. *
  105. * Get the printer name from the path
  106. *
  107. \*****************************************************************************/
  108. LPTSTR GetPrinterName (LPTSTR lpszPathInfo)
  109. {
  110. // The only format we support is "/printers/ShareName|Encoded Printer Name/.printer"
  111. static TCHAR szPrinter[] = TEXT ("/.printer");
  112. static TCHAR szPrinters[] = TEXT ("/printers/");
  113. LPTSTR lpPtr = NULL;
  114. LPTSTR lpPathInfo = NULL;
  115. LPTSTR lpPrinterName = NULL;
  116. LPTSTR lpSuffix = NULL;
  117. DWORD dwLen;
  118. // Make a copy of lpszPathInfo
  119. if (! (lpPathInfo = lpPtr = AllocStr (lpszPathInfo)))
  120. return NULL;
  121. // Verify the prefix
  122. if (_tcsnicmp (lpPathInfo, szPrinters, COUNTOF (szPrinters) - 1)) {
  123. goto Cleanup;
  124. }
  125. lpPathInfo += COUNTOF (szPrinters) - 1;
  126. dwLen = lstrlen (lpPathInfo);
  127. // Compare the length of the printer name with .printer suffix
  128. if (dwLen <= COUNTOF (szPrinter) - 1) {
  129. goto Cleanup;
  130. }
  131. lpSuffix = lpPathInfo + dwLen - COUNTOF (szPrinter) + 1;
  132. //lpszStr should point to .printer
  133. // Verify the suffix.
  134. if (lstrcmpi(lpSuffix, szPrinter)) {
  135. goto Cleanup;
  136. }
  137. *lpSuffix = TEXT('\0'); // Terminate string
  138. lpPrinterName = AllocStr (lpPathInfo);
  139. Cleanup:
  140. LocalFree(lpPtr);
  141. return lpPrinterName;
  142. }
  143. /*****************************************************************************\
  144. * DllMain
  145. *
  146. *
  147. \*****************************************************************************/
  148. BOOL WINAPI DllMain (HINSTANCE hinstDLL, DWORD fdwReason,
  149. LPVOID lpvReserved)
  150. {
  151. BOOL bRet = TRUE;
  152. if (fdwReason == DLL_PROCESS_ATTACH)
  153. {
  154. g_hInstance = hinstDLL;
  155. // Init debug support in spllib.lib
  156. bSplLibInit( NULL );
  157. __try {
  158. InitializeCriticalSection(&SplCritSect);
  159. InitializeCriticalSection(&TagCritSect);
  160. // Initialize the CAB generation crit-sect for web-pnp.
  161. //
  162. InitCABCrit();
  163. }
  164. __except (1) {
  165. bRet = FALSE;
  166. SetLastError (ERROR_INVALID_HANDLE);
  167. }
  168. if (bRet) {
  169. // Initializa the sleeper, which is used to cleanup the pritner jobs
  170. InitSleeper ();
  171. // We don't care about fdwReason==DLL_THREAD_ATTACH or _DETACH
  172. DisableThreadLibraryCalls(hinstDLL);
  173. srand( (UINT)time( NULL ) );
  174. }
  175. }
  176. if (fdwReason == DLL_PROCESS_DETACH)
  177. {
  178. // Terminate the additional cleanup thread
  179. ExitSleeper ();
  180. DeleteCriticalSection(&SplCritSect);
  181. DeleteCriticalSection(&TagCritSect);
  182. // Free our web-pnp crit-sect.
  183. //
  184. FreeCABCrit();
  185. // Free debug support in spllib.lib
  186. vSplLibFree();
  187. }
  188. // Do any other required initialize/deinitialize here.
  189. return bRet;
  190. }
  191. /*****************************************************************************\
  192. * GetExtensionVersion
  193. *
  194. * Required ISAPI export function.
  195. *
  196. \*****************************************************************************/
  197. BOOL WINAPI GetExtensionVersion(
  198. HSE_VERSION_INFO *pVer)
  199. {
  200. pVer->dwExtensionVersion = MAKELONG( HSE_VERSION_MINOR, HSE_VERSION_MAJOR );
  201. TCHAR szBuf[HSE_MAX_EXT_DLL_NAME_LEN+1];
  202. szBuf[0] = TEXT('\0');
  203. LoadString(g_hInstance, IDS_ISAPI_DESCRIPTION, szBuf, sizeof(szBuf) / sizeof (TCHAR));
  204. // Convert szBuf to ANSI
  205. if (UnicodeToAnsiString (szBuf, (LPSTR) szBuf, NULL)) {
  206. lstrcpynA( pVer->lpszExtensionDesc, (LPSTR) szBuf,
  207. HSE_MAX_EXT_DLL_NAME_LEN );
  208. return TRUE;
  209. }
  210. else
  211. return FALSE;
  212. } // GetExtensionVersion()
  213. /*****************************************************************************\
  214. * GetServerName
  215. *
  216. * Get the server name and convert it to the unicode string.
  217. *
  218. \*****************************************************************************/
  219. BOOL GetServerName (EXTENSION_CONTROL_BLOCK *pECB)
  220. {
  221. static char c_szServerName[] = "SERVER_NAME";
  222. DWORD dwSize;
  223. char szAnsiHttpServerName[INTERNET_MAX_HOST_NAME_LENGTH + 1];
  224. BOOL bRet = FALSE;
  225. DWORD dwClusterState;
  226. BOOL bCluster = FALSE;
  227. dwSize = sizeof(szAnsiHttpServerName);
  228. if (pECB->GetServerVariable (pECB->ConnID, c_szServerName, szAnsiHttpServerName, &dwSize)) {
  229. AnsiToUnicodeString(szAnsiHttpServerName, g_szHttpServerName, 0);
  230. // Now, the computer name becomes the server name. In case of the intranet, it is the computer
  231. // name, in case of internet, it is either the IP address or the DNS name
  232. if (!lstrcmpi (g_szHttpServerName, TEXT ("localhost")) ||
  233. !lstrcmpi (g_szHttpServerName, TEXT ("127.0.0.1"))) {
  234. dwSize = ARRAY_COUNT (g_szHttpServerName);
  235. bRet = GetComputerName( g_szHttpServerName, &dwSize);
  236. }
  237. else
  238. bRet = TRUE;
  239. }
  240. if (bRet) {
  241. bRet = FALSE;
  242. // Now let's get the printer server name
  243. //
  244. // Check if we are running in a cluster node
  245. //
  246. if ((GetNodeClusterState (NULL, &dwClusterState) == ERROR_SUCCESS) &&
  247. (dwClusterState == ClusterStateRunning)) {
  248. bCluster = TRUE;
  249. }
  250. //
  251. // If we are running in the cluster mode, we have to use the ServerName referred in the HTTP header.
  252. // Otherwise, we can use the computer name directly.
  253. //
  254. // Get size in Charaters of the buffer
  255. dwSize = ARRAY_COUNT (g_szPrintServerName);
  256. if (bCluster)
  257. {
  258. if (SUCCEEDED( StringCchCopy (g_szPrintServerName, dwSize, g_szHttpServerName)))
  259. bRet = TRUE;
  260. }
  261. else
  262. {
  263. bRet = GetComputerName( g_szPrintServerName, &dwSize);
  264. }
  265. }
  266. return bRet;
  267. }
  268. /*****************************************************************************\
  269. * ParseQueryString
  270. *
  271. * ParseQueryString converts the query string into a sequence of arguments.
  272. * The main command is converted to a command ID. Subsequent arguments are
  273. * converted to strings or DWORDs.
  274. *
  275. * Format: Command & Arg1 & Arg2 & Arg3 ...
  276. * Each arg is either a number or a string in quotes.
  277. *
  278. * returns FALSE if the query string exists but is invalid
  279. *
  280. \*****************************************************************************/
  281. BOOL ParseQueryString(PALLINFO pAllInfo)
  282. {
  283. LPTSTR pszQueryString, pszTmp, pszTmp2, pszTmp3;
  284. int iNumArgs = 0;
  285. pszQueryString = pAllInfo->lpszQueryString;
  286. if ( !pszQueryString || (*pszQueryString == 0) )
  287. {
  288. // Check if the method is post
  289. if ( !lstrcmp (pAllInfo->lpszMethod, TEXT ("POST")) )
  290. {
  291. // also check here for content-type application/ipp ???
  292. //
  293. pAllInfo->iQueryCommand = CMD_IPP; // can we use the NULL cmd ???
  294. }
  295. else
  296. {
  297. pAllInfo->iQueryCommand = CMD_WebUI; // redirect to webui
  298. }
  299. return TRUE;
  300. }
  301. // Get a copy of the string to do surgery on it in this routine and save pieces of it as other info.
  302. // Save it too so it can be freed later.
  303. pszQueryString = AllocStr ( pszQueryString );
  304. if ( pszQueryString != NULL )
  305. {
  306. // We will find and replace the first '&' with NULL. This is to isolate the first
  307. // piece of the query string and examine it.
  308. // pszQueryString then points to this first piece (command), pszTmp to the rest.
  309. if ( pszTmp = _tcschr( pszQueryString, TEXT('&')) )
  310. {
  311. *pszTmp = TEXT('\0');
  312. pszTmp++;
  313. }
  314. // Search for main command
  315. pAllInfo->iQueryCommand = CMD_Invalid;
  316. // If we had {WinPrint.PrinterCommandURL}?/myfile.htm&bla1&bla2&bla3.....
  317. // or {WinPrint.PrinterCommandURL}?/bla1/bla2/.../blaN/myfile.htm&aaa&bbb&ccc...
  318. // then pszQueryString is pointing to a NULL we inserted in place of '/', so it is OK.
  319. // So just attempt to find a iQueryCommand only if pszQueryString is pointing to a non-NULL char.
  320. if ( *pszQueryString )
  321. {
  322. for ( int i=0; i<iNumQueryMap; i++ )
  323. {
  324. if ( !lstrcmpi(rgQueryMap[i].pszCommand, pszQueryString) )
  325. {
  326. pAllInfo->iQueryCommand = rgQueryMap[i].iCommandID;
  327. break;
  328. }
  329. }
  330. if ( pAllInfo->iQueryCommand == CMD_Invalid )
  331. {
  332. LocalFree( pszQueryString );
  333. return FALSE; // No command found. Bad query string.
  334. }
  335. }
  336. // At this point we continue with pszTmp for the arguments.
  337. // We take at most MAX_Q_ARG arguments to avoid memory corruption
  338. while ( (NULL != pszTmp) && (*pszTmp) && iNumArgs < MAX_Q_ARG )
  339. {
  340. pszTmp2 = pszTmp;
  341. pszTmp = _tcschr( pszTmp, TEXT('&'));
  342. if ( pszTmp != NULL )
  343. {
  344. *pszTmp = 0;
  345. pszTmp ++;
  346. }
  347. if ( *pszTmp2 >= TEXT('0') && *pszTmp2 <= TEXT('9') )
  348. {
  349. // DWORD integer value
  350. pAllInfo->fQueryArgIsNum[iNumArgs] = TRUE;
  351. pAllInfo->QueryArgValue[iNumArgs] = (DWORD)_ttoi(pszTmp2);
  352. }
  353. else
  354. {
  355. // Pointer to string
  356. pAllInfo->fQueryArgIsNum[iNumArgs] = FALSE;
  357. pAllInfo->QueryArgValue[iNumArgs] = (UINT_PTR)pszTmp2;
  358. }
  359. iNumArgs ++;
  360. }
  361. pAllInfo->iNumQueryArgs = iNumArgs;
  362. DBGMSG(DBG_INFO, ("ParseQueryString: %d query arguments\r\n", iNumArgs));
  363. LocalFree( pszQueryString );
  364. return TRUE;
  365. }
  366. return FALSE;
  367. }
  368. /*****************************************************************************\
  369. * CreateExe
  370. *
  371. *
  372. \*****************************************************************************/
  373. DWORD CreateExe(PALLINFO pAllInfo, PPRINTERPAGEINFO pPageInfo, DWORD dwCliInfo)
  374. {
  375. LPTSTR lpPortName = NULL;
  376. LPTSTR lpExeName = NULL;
  377. LPTSTR lpFriendlyName = NULL;
  378. DWORD dwRet = HSE_STATUS_ERROR ;
  379. DWORD dwLen = 0;
  380. DWORD dwFNBytes = 0;
  381. DWORD dwLastError = ERROR_INVALID_DATA;
  382. BOOL bSecure = IsSecureReq (pAllInfo->pECB);
  383. GetWebpnpUrl (g_szHttpServerName, pPageInfo->pPrinterInfo->pShareName, NULL, bSecure, NULL, &dwLen);
  384. if (GetLastError () != ERROR_INSUFFICIENT_BUFFER)
  385. goto Cleanup;
  386. if (! (lpPortName = (LPTSTR)LocalAlloc(LPTR, dwLen * sizeof (*lpPortName))))
  387. goto Cleanup;
  388. if (!GetWebpnpUrl (g_szHttpServerName, pPageInfo->pPrinterInfo->pShareName, NULL, bSecure, lpPortName, &dwLen))
  389. goto Cleanup;
  390. lpExeName = (LPTSTR)LocalAlloc(LPTR, MAX_PATH * sizeof (*lpExeName));
  391. if (!lpExeName)
  392. goto Cleanup;
  393. dwFNBytes = (lstrlen(pPageInfo->pszFriendlyName)+1) * sizeof (*lpFriendlyName);
  394. lpFriendlyName = (LPTSTR)LocalAlloc(LPTR, dwFNBytes);
  395. if (!lpFriendlyName)
  396. goto Cleanup;
  397. if (FAILED( StringCbCopy(lpFriendlyName, dwFNBytes, pPageInfo->pszFriendlyName)))
  398. goto Cleanup;
  399. dwRet = GenerateCAB(lpFriendlyName,
  400. lpPortName,
  401. dwCliInfo,
  402. lpExeName,
  403. IsSecureReq(pAllInfo->pECB));
  404. if (dwRet == HSE_STATUS_SUCCESS) {
  405. LPTSTR lpEncodedExeName = EncodeString (lpExeName, TRUE);
  406. if (!lpEncodedExeName) {
  407. dwRet = HSE_STATUS_ERROR;
  408. goto Cleanup;
  409. }
  410. htmlSendRedirect (pAllInfo, lpEncodedExeName);
  411. LocalFree (lpEncodedExeName);
  412. }
  413. else {
  414. dwLastError = GetLastError ();
  415. if (dwLastError == ERROR_FILE_NOT_FOUND) {
  416. dwLastError = ERROR_DRIVER_NOT_FOUND;
  417. }
  418. if (dwLastError == ERROR_DISK_FULL) {
  419. dwLastError = ERROR_SERVER_DISK_FULL;
  420. }
  421. }
  422. Cleanup:
  423. LocalFree(lpPortName);
  424. LocalFree(lpExeName);
  425. LocalFree(lpFriendlyName);
  426. if (dwRet != HSE_STATUS_SUCCESS)
  427. return ProcessErrorMessage (pAllInfo, dwLastError);
  428. else
  429. return dwRet;
  430. }
  431. /*****************************************************************************\
  432. * ProcessRequest
  433. *
  434. * Process the incoming request
  435. *
  436. \*****************************************************************************/
  437. DWORD ProcessRequest(PALLINFO pAllInfo, LPTSTR lpszPrinterName)
  438. {
  439. DWORD dwRet = HSE_STATUS_ERROR;
  440. PPRINTER_INFO_2 pPrinterInfo = NULL;
  441. HANDLE hPrinter = NULL;
  442. DWORD iQueryCommand;
  443. LPTSTR lpszFriendlyName;
  444. DWORD dwCliInfo;
  445. WORD wIppReq = 0;
  446. LPTSTR pszDecodedName = NULL;
  447. DWORD dwSize = 0;
  448. PRINTER_DEFAULTS pd = {NULL, NULL, PRINTER_ACCESS_USE};
  449. LPTSTR lpszWebUIUrl = NULL;
  450. LPTSTR pszOpenName = NULL;
  451. LPTSTR pszTmpName = NULL;
  452. iQueryCommand = pAllInfo->iQueryCommand;
  453. DBGMSG(DBG_INFO, ("ShowPrinterPage for printer \"%ws\"\n", lpszPrinterName));
  454. // Open the printer and get printer info level 2.
  455. DecodePrinterName (lpszPrinterName, NULL, &dwSize);
  456. if (! (pszDecodedName = (LPTSTR) LocalAlloc (LPTR, sizeof (TCHAR) * dwSize)))
  457. return ProcessErrorMessage (pAllInfo, GetLastError ());
  458. if (!DecodePrinterName (lpszPrinterName, pszDecodedName, &dwSize)) {
  459. dwRet = ProcessErrorMessage (pAllInfo, GetLastError ());
  460. goto Cleanup;
  461. }
  462. if (*pszDecodedName != TEXT ('\\') )
  463. {
  464. dwSize = sizeof(TCHAR) * (lstrlen (pszDecodedName) + lstrlen (g_szPrintServerName) + 4 );
  465. // There is no server name before the printer name, append the server name
  466. if (! (pszOpenName = pszTmpName = (LPTSTR) LocalAlloc (LPTR, dwSize)))
  467. goto Cleanup;
  468. StringCbCopy (pszOpenName, dwSize, TEXT ("\\\\"));
  469. StringCbCat (pszOpenName, dwSize, g_szPrintServerName);
  470. StringCbCat (pszOpenName, dwSize, TEXT ("\\"));
  471. StringCbCat (pszOpenName, dwSize, pszDecodedName);
  472. }
  473. else {
  474. pszOpenName = pszDecodedName;
  475. }
  476. if (! OpenPrinter(pszOpenName, &hPrinter, &pd)) {
  477. dwRet = ProcessErrorMessage (pAllInfo, GetLastError ());
  478. goto Cleanup;
  479. }
  480. // Get a PRINTER_INFO_2 structure filled up
  481. dwSize = 0;
  482. GetPrinter(hPrinter, 2, NULL, 0, &dwSize);
  483. if ((GetLastError() != ERROR_INSUFFICIENT_BUFFER) ||
  484. (NULL == (pPrinterInfo = (PPRINTER_INFO_2)LocalAlloc(LPTR, dwSize))) ||
  485. (!GetPrinter(hPrinter, 2, (byte *)pPrinterInfo, dwSize, &dwSize))) {
  486. dwRet = ProcessErrorMessage (pAllInfo, GetLastError ());
  487. goto Cleanup;
  488. }
  489. if (! (pPrinterInfo->Attributes & PRINTER_ATTRIBUTE_SHARED)) {
  490. // If the printer is not shared, return access denied
  491. dwRet = ProcessErrorMessage (pAllInfo, ERROR_ACCESS_DENIED);
  492. goto Cleanup;
  493. }
  494. // Find printer friendly name.
  495. // If we opened with UNC path we need to remove server name
  496. if (pPrinterInfo->pPrinterName) {
  497. lpszFriendlyName = _tcsrchr (pPrinterInfo->pPrinterName, TEXT('\\'));
  498. if (lpszFriendlyName)
  499. lpszFriendlyName ++;
  500. else
  501. lpszFriendlyName = pPrinterInfo->pPrinterName;
  502. }
  503. // We've got an open printer and some printer info. Ready to go.
  504. // Fill in structure of info for whatever function we call
  505. PRINTERPAGEINFO ppi;
  506. ZeroMemory(&ppi, sizeof(ppi));
  507. ppi.pszFriendlyName = lpszFriendlyName;
  508. ppi.pPrinterInfo = pPrinterInfo;
  509. ppi.hPrinter = hPrinter;
  510. // Do appropriate action based on query string
  511. switch (iQueryCommand) {
  512. case CMD_WebUI:
  513. // Construct a URL to redirect
  514. dwSize = 0;
  515. if (GetWebUIUrl (NULL, pszDecodedName, lpszWebUIUrl, &dwSize))
  516. goto Cleanup;
  517. if (GetLastError () != ERROR_INSUFFICIENT_BUFFER)
  518. goto Cleanup;
  519. if (!(lpszWebUIUrl = (LPTSTR)LocalAlloc(LPTR, dwSize * sizeof (TCHAR))))
  520. goto Cleanup;
  521. if (! GetWebUIUrl (NULL, pszDecodedName, lpszWebUIUrl, &dwSize))
  522. goto Cleanup;
  523. dwRet = htmlSendRedirect (pAllInfo, lpszWebUIUrl);
  524. break;
  525. case CMD_IPP:
  526. if (wIppReq = GetIppReq(pAllInfo)) {
  527. dwRet = SplIppJob(wIppReq, pAllInfo, &ppi);
  528. } else {
  529. DBGMSG(DBG_WARN, ("ShowPrinterPage: Warn : Invalid IPP Stream.\n"));
  530. if (IsClientHttpProvider (pAllInfo)){
  531. // To improve the perfomance for the internet provider by returning something really quick
  532. LPTSTR pszContent = GetString(pAllInfo, IDS_ERROR_200CONTENT);
  533. htmlSendHeader (pAllInfo, TEXT ("200 OK"), pszContent);
  534. dwRet = HSE_STATUS_SUCCESS;
  535. }
  536. if (INVALID_HANDLE_VALUE != hPrinter)
  537. ClosePrinter(hPrinter);
  538. break;
  539. }
  540. break;
  541. case CMD_CreateExe:
  542. DBGMSG(DBG_TRACE, ("Calling CreateExe.\n"));
  543. if (dwCliInfo = GetClientInfo(pAllInfo)) {
  544. dwRet = CreateExe(pAllInfo, &ppi, dwCliInfo);
  545. } else {
  546. dwRet = ProcessErrorMessage (pAllInfo, ERROR_NOT_SUPPORTED);
  547. goto Cleanup;
  548. }
  549. break;
  550. default:
  551. dwRet = ProcessErrorMessage (pAllInfo, ERROR_INVALID_PRINTER_COMMAND);
  552. break;
  553. }
  554. Cleanup:
  555. // Clean up our stuff
  556. if (dwRet != HSE_STATUS_ERROR)
  557. pAllInfo->pECB->dwHttpStatusCode=200; // 200 OK
  558. LocalFree (lpszWebUIUrl);
  559. LocalFree (pszDecodedName);
  560. LocalFree (pszTmpName);
  561. LocalFree (pPrinterInfo);
  562. // For any commands other than CMD_IPP commands, we can close the
  563. // printer-handle. Otherwise, we rely on the Spool*() routines
  564. // to handle this for us after we're done reading and processing
  565. // the entire print-job.
  566. //
  567. if (hPrinter && (iQueryCommand != CMD_IPP))
  568. ClosePrinter(hPrinter);
  569. return dwRet;
  570. }
  571. /*****************************************************************************\
  572. * GetString
  573. *
  574. *
  575. \*****************************************************************************/
  576. LPTSTR GetString(PALLINFO pAllInfo, UINT iStringID)
  577. {
  578. LPTSTR lpszBuf = pAllInfo->szStringBuf;
  579. lpszBuf[0] = TEXT('\0');
  580. LoadString(g_hInstance, iStringID, lpszBuf, STRBUFSIZE);
  581. SPLASSERT(lpszBuf[0] != TEXT('\0'));
  582. return lpszBuf;
  583. }
  584. /*****************************************************************************\
  585. * HttpExtensionProc
  586. *
  587. * Main entrypoint for HTML generation.
  588. *
  589. \*****************************************************************************/
  590. DWORD WINAPI HttpExtensionProc(
  591. EXTENSION_CONTROL_BLOCK *pECB)
  592. {
  593. DWORD dwRet = HSE_STATUS_ERROR;
  594. PALLINFO pAllInfo = NULL; // This structure contains all relevant info for this connection
  595. LPTSTR pPrinterName = NULL;
  596. // Assume failure
  597. if(!pECB) return HSE_STATUS_ERROR;
  598. pECB->dwHttpStatusCode = HTTP_STATUS_NOT_SUPPORTED;
  599. // Get the server name and convert it to the unicode string.
  600. if (!GetServerName (pECB))
  601. return HSE_STATUS_ERROR;
  602. if (!(pAllInfo = (PALLINFO) LocalAlloc (LPTR, sizeof (ALLINFO))))
  603. return HSE_STATUS_ERROR;
  604. // Initialize pAllInfo
  605. ZeroMemory(pAllInfo, sizeof(ALLINFO));
  606. pAllInfo->pECB = pECB;
  607. // Convert the ANSI string in ECB to Unicode
  608. // weihaic
  609. // pAllInfo->lpszQueryString = AllocateUnicodeString(DecodeStringA (pECB->lpszQueryString));
  610. // We can not decode now becuase the decoded string will bring troubles in parsing
  611. //
  612. pAllInfo->lpszQueryString = AllocateUnicodeString(pECB->lpszQueryString);
  613. pAllInfo->lpszMethod = AllocateUnicodeString(pECB->lpszMethod);
  614. pAllInfo->lpszPathInfo = AllocateUnicodeString(pECB->lpszPathInfo);
  615. pAllInfo->lpszPathTranslated = AllocateUnicodeString(pECB->lpszPathTranslated);
  616. if (!pAllInfo->lpszQueryString ||
  617. !pAllInfo->lpszMethod ||
  618. !pAllInfo->lpszPathInfo ||
  619. !pAllInfo->lpszPathTranslated ) {
  620. goto Cleanup;
  621. }
  622. // weihaic
  623. // The query string contain user entered text such as printer location
  624. // priner description, etc. These strings are case sensitive, so we
  625. // could not convert them to upper case at the very beginning
  626. // CharUpper (pAllInfo->lpszQueryString);
  627. //
  628. CharUpper (pAllInfo->lpszMethod);
  629. CharUpper (pAllInfo->lpszPathInfo);
  630. CharUpper (pAllInfo->lpszPathTranslated);
  631. if (! (pPrinterName = GetPrinterName (pAllInfo->lpszPathInfo))) {
  632. // This is a wrong URL, return error code
  633. dwRet = ProcessErrorMessage (pAllInfo, ERROR_INVALID_DATA);
  634. goto Cleanup;
  635. }
  636. if (! ParseQueryString (pAllInfo))
  637. goto Cleanup;
  638. dwRet = ProcessRequest (pAllInfo, pPrinterName); // We always hit Cleanup anyway
  639. Cleanup:
  640. LocalFree (pPrinterName);
  641. LocalFree (pAllInfo->lpszQueryString);
  642. LocalFree (pAllInfo->lpszMethod);
  643. LocalFree (pAllInfo->lpszPathInfo);
  644. LocalFree (pAllInfo->lpszPathTranslated);
  645. LocalFree (pAllInfo);
  646. return dwRet;
  647. } // HttpExtensionProc()