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.

226 lines
5.7 KiB

  1. /*****************************************************************************\
  2. * MODULE: util.cpp
  3. *
  4. * PURPOSE: Tools for OlePrn project
  5. *
  6. * Copyright (C) 1997-1998 Microsoft Corporation
  7. *
  8. * History:
  9. *
  10. * 08/16/97 paulmo Created
  11. * 09/12/97 weihaic Added more functions
  12. * 10/28/97 keithst Added SetScriptingError
  13. * 11/06/97 keithst Removed Win2ComErr
  14. *
  15. \*****************************************************************************/
  16. #include "stdafx.h"
  17. //---------------------------------------------
  18. // Put an ANSI string into a SAFEARRAY
  19. //
  20. //
  21. // Convert the string into UNICODE
  22. // Make a BSTR out of it
  23. // Add it to the array
  24. //
  25. HRESULT PutString(SAFEARRAY *psa, long *ix, LPSTR sz)
  26. {
  27. LPWSTR lpWstr;
  28. VARIANT var;
  29. HRESULT hr;
  30. VariantInit(&var);
  31. var.vt = VT_BSTR;
  32. if (sz == NULL)
  33. lpWstr = MakeWide("");
  34. else
  35. lpWstr = MakeWide(sz);
  36. if (lpWstr == NULL) return E_OUTOFMEMORY;
  37. var.bstrVal = SysAllocString(lpWstr);
  38. LocalFree(lpWstr);
  39. if (var.bstrVal == NULL)
  40. return E_OUTOFMEMORY;
  41. hr = SafeArrayPutElement(psa, ix, &var);
  42. VariantClear(&var);
  43. return hr;
  44. }
  45. // ---------------------------------------------
  46. // Convert an ANSI string to UNICODE
  47. //
  48. // Note - you must LocalFree the returned string
  49. //
  50. LPWSTR MakeWide(LPSTR psz)
  51. {
  52. LPWSTR buff;
  53. int i;
  54. i = MultiByteToWideChar(CP_ACP, 0, psz, -1, NULL, 0);
  55. buff = (LPWSTR)LocalAlloc(LPTR, i * 2);
  56. if (buff == NULL)
  57. return NULL;
  58. i = MultiByteToWideChar(CP_ACP, 0, psz, -1, buff, i);
  59. return buff;
  60. }
  61. //-------------------------------------------------
  62. // Convert a UNICODE string to ANSI
  63. //
  64. // Note - you must LocalFree the returned string
  65. //
  66. LPSTR MakeNarrow(LPWSTR str)
  67. {
  68. LPSTR buff;
  69. int i;
  70. i = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0, NULL, NULL);
  71. buff = (LPSTR )LocalAlloc(LPTR, i);
  72. if (buff == NULL)
  73. return NULL;
  74. i = WideCharToMultiByte(CP_ACP, 0, str, -1, buff, i, NULL, NULL);
  75. return buff;
  76. }
  77. //-------------------------------------------------
  78. // SetScriptingError
  79. // Takes a Win32 error code and sets the associated string as
  80. // the scripting language error description
  81. //
  82. // Parameters:
  83. // CLSID *pclsid: pointer to Class ID (CLSID) for the class which
  84. // generated the error; passed to AtlReportError
  85. //
  86. // IID *piid: pointer to interface ID (IID) for the interface
  87. // which generated the error; passed to AtlReportError
  88. //
  89. // DWORD dwError: the error code retrieved from GetLastError by
  90. // the caller of this function
  91. //
  92. // Return Value:
  93. // This function uses the HRESULT_FROM_WIN32 macro, which translates
  94. // the Win32 dwError code to a COM error code. This COM error code
  95. // should be returned out as the return value of the failed method.
  96. //
  97. HRESULT SetScriptingError(const CLSID& rclsid, const IID& riid, DWORD dwError)
  98. {
  99. LPTSTR lpMsgBuf = NULL;
  100. DWORD dwRet = 0;
  101. dwRet = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
  102. FORMAT_MESSAGE_FROM_SYSTEM |
  103. FORMAT_MESSAGE_IGNORE_INSERTS,
  104. NULL,
  105. dwError,
  106. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  107. (LPTSTR) &lpMsgBuf,
  108. 0,
  109. NULL);
  110. if (dwRet == 0 || !lpMsgBuf)
  111. {
  112. //
  113. // If FormatMessage fails, it returns 0, but since we can not call
  114. // GetLastError again, we return OUTOFMEMORY instead.
  115. //
  116. return E_OUTOFMEMORY;
  117. }
  118. AtlReportError(rclsid, lpMsgBuf, riid, HRESULT_FROM_WIN32(dwError));
  119. LocalFree(lpMsgBuf);
  120. return (HRESULT_FROM_WIN32(dwError));
  121. }
  122. HANDLE
  123. RevertToPrinterSelf(
  124. VOID)
  125. {
  126. HANDLE NewToken, OldToken;
  127. NTSTATUS Status;
  128. NewToken = NULL;
  129. Status = NtOpenThreadToken(
  130. NtCurrentThread(),
  131. TOKEN_IMPERSONATE,
  132. TRUE,
  133. &OldToken
  134. );
  135. if ( !NT_SUCCESS(Status) ) {
  136. SetLastError(Status);
  137. return FALSE;
  138. }
  139. Status = NtSetInformationThread(
  140. NtCurrentThread(),
  141. ThreadImpersonationToken,
  142. (PVOID)&NewToken,
  143. (ULONG)sizeof(HANDLE)
  144. );
  145. if ( !NT_SUCCESS(Status) ) {
  146. SetLastError(Status);
  147. return FALSE;
  148. }
  149. return OldToken;
  150. }
  151. BOOL
  152. ImpersonatePrinterClient(
  153. HANDLE hToken)
  154. {
  155. NTSTATUS Status;
  156. Status = NtSetInformationThread(
  157. NtCurrentThread(),
  158. ThreadImpersonationToken,
  159. (PVOID)&hToken,
  160. (ULONG)sizeof(HANDLE)
  161. );
  162. if ( !NT_SUCCESS(Status) ) {
  163. SetLastError(Status);
  164. return FALSE;
  165. }
  166. NtClose(hToken);
  167. return TRUE;
  168. }
  169. DWORD MyDeviceCapabilities(
  170. LPCTSTR pDevice, // pointer to a printer-name string
  171. LPCTSTR pPort, // pointer to a port-name string
  172. WORD fwCapability, // device capability to query
  173. LPTSTR pOutput, // pointer to the output
  174. CONST DEVMODE *pDevMode
  175. // pointer to structure with device data
  176. )
  177. {
  178. DWORD dwRet = DWERROR;
  179. HANDLE hToken = NULL;
  180. dwRet = DeviceCapabilities(pDevice, pPort, fwCapability, pOutput, pDevMode);
  181. if (dwRet == DWERROR && GetLastError () == ERROR_ACCESS_DENIED) {
  182. // In a cluster machine, we need to get the local admin previlige to get
  183. // the device capabilities.
  184. if (hToken = RevertToPrinterSelf()) {
  185. dwRet = DeviceCapabilities(pDevice, pPort, fwCapability, pOutput, pDevMode);
  186. ImpersonatePrinterClient(hToken);
  187. }
  188. }
  189. return dwRet;
  190. }