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.

532 lines
15 KiB

  1. #include "precomp.h"
  2. // this class is used by our private wrappers to thunk unicode to ansi and take care of
  3. // all the allocation goo. There are three constructors: use LPCWSTR if you just need
  4. // to thunk a normal string to ansi, use LPCWSTR, LPDWORD if you need to thunk a list of
  5. // null-terminated strings to ansi, and use DWORD if you need a buffer for an out
  6. // parameter
  7. class CAnsiStr
  8. {
  9. private:
  10. CHAR m_szBuf[MAX_PATH];
  11. BOOL m_fFree;
  12. public:
  13. LPSTR pszStr;
  14. CAnsiStr(LPCWSTR);
  15. CAnsiStr(LPCWSTR, LPDWORD pcchSize);
  16. CAnsiStr(DWORD cchSize);
  17. ~CAnsiStr();
  18. };
  19. CAnsiStr::CAnsiStr(LPCWSTR pcwszStr)
  20. {
  21. if (pcwszStr == NULL)
  22. {
  23. m_fFree = FALSE;
  24. pszStr = NULL;
  25. }
  26. else
  27. {
  28. DWORD cchSize = StrLenW(pcwszStr);
  29. DWORD cbSize, dwErr;
  30. m_fFree = (cchSize > (countof(m_szBuf) - 1));
  31. if (m_fFree)
  32. {
  33. pszStr = (LPSTR)CoTaskMemAlloc(cchSize+1);
  34. if (pszStr == NULL)
  35. {
  36. m_fFree = FALSE;
  37. return;
  38. }
  39. else
  40. ZeroMemory(pszStr, cchSize+1);
  41. }
  42. else
  43. pszStr = m_szBuf;
  44. cbSize = WideCharToMultiByte(CP_ACP, 0, pcwszStr, cchSize+1, pszStr, cchSize+1, NULL, NULL);
  45. dwErr = GetLastError();
  46. // NOTE: check to see if we fail, in which case we might be dealing with DBCS chars and
  47. // need to reallocate or allocate
  48. if ((cbSize == 0) && (dwErr == ERROR_INSUFFICIENT_BUFFER))
  49. {
  50. cbSize = WideCharToMultiByte(CP_ACP, 0, pcwszStr, cchSize+1, pszStr, 0, NULL, NULL);
  51. if (m_fFree)
  52. {
  53. LPSTR pszStr2;
  54. // need this second ptr because CoTaskMemRealloc doesn't free the old block if
  55. // not enough mem for the new one
  56. pszStr2 = (LPSTR)CoTaskMemRealloc(pszStr, cbSize);
  57. if (pszStr2 == NULL)
  58. CoTaskMemFree(pszStr);
  59. pszStr = pszStr2;
  60. }
  61. else
  62. {
  63. m_fFree = (cbSize > countof(m_szBuf));
  64. if (m_fFree)
  65. pszStr = (LPSTR)CoTaskMemAlloc(cbSize);
  66. }
  67. if (m_fFree && (pszStr == NULL))
  68. {
  69. m_fFree = FALSE;
  70. return;
  71. }
  72. WideCharToMultiByte(CP_ACP, 0, pcwszStr, cchSize+1, pszStr, cbSize, NULL, NULL);
  73. }
  74. }
  75. }
  76. CAnsiStr::CAnsiStr(LPCWSTR pcwszStr, LPDWORD pcchSize)
  77. {
  78. if (pcchSize != NULL)
  79. *pcchSize = 0;
  80. if (pcwszStr == NULL)
  81. {
  82. m_fFree = FALSE;
  83. pszStr = NULL;
  84. }
  85. else
  86. {
  87. DWORD cchSize = 0;
  88. DWORD cbSize, dwErr;
  89. for (LPCWSTR pcwsz = pcwszStr; *pcwsz; )
  90. {
  91. DWORD cchStrSize = StrLenW(pcwsz)+1;
  92. cchSize += cchStrSize;
  93. pcwsz += cchStrSize;
  94. }
  95. m_fFree = (cchSize > (ARRAYSIZE(m_szBuf) - 1));
  96. if (m_fFree)
  97. {
  98. pszStr = (LPSTR)CoTaskMemAlloc(cchSize+1);
  99. if (pszStr == NULL)
  100. {
  101. m_fFree = FALSE;
  102. return;
  103. }
  104. else
  105. ZeroMemory(pszStr, cchSize+1);
  106. }
  107. else
  108. pszStr = m_szBuf;
  109. cbSize = WideCharToMultiByte(CP_ACP, 0, pcwszStr, cchSize+1, pszStr, cchSize+1, NULL, NULL);
  110. dwErr = GetLastError();
  111. // NOTE: check to see if we fail, in which case we might be dealing with DBCS chars and
  112. // need to reallocate or allocate
  113. if ((cbSize == 0) && (dwErr == ERROR_INSUFFICIENT_BUFFER))
  114. {
  115. cbSize = WideCharToMultiByte(CP_ACP, 0, pcwszStr, cchSize+1, pszStr, 0, NULL, NULL);
  116. if (m_fFree)
  117. {
  118. LPSTR pszStr2;
  119. // need this second ptr because CoTaskMemRealloc doesn't free the old block if
  120. // not enough mem for the new one
  121. pszStr2 = (LPSTR)CoTaskMemRealloc(pszStr, cbSize);
  122. if (pszStr2 == NULL)
  123. CoTaskMemFree(pszStr);
  124. pszStr = pszStr2;
  125. }
  126. else
  127. {
  128. m_fFree = (cbSize > countof(m_szBuf));
  129. if (m_fFree)
  130. pszStr = (LPSTR)CoTaskMemAlloc(cbSize);
  131. }
  132. if (m_fFree && (pszStr == NULL))
  133. {
  134. m_fFree = FALSE;
  135. return;
  136. }
  137. WideCharToMultiByte(CP_ACP, 0, pcwszStr, cchSize+1, pszStr, cbSize, NULL, NULL);
  138. }
  139. if (pcchSize != NULL)
  140. *pcchSize = cchSize;
  141. }
  142. }
  143. CAnsiStr::CAnsiStr(DWORD cchSize)
  144. {
  145. m_fFree = (cchSize > ARRAYSIZE(m_szBuf));
  146. if (m_fFree)
  147. {
  148. pszStr = (LPSTR)CoTaskMemAlloc(cchSize);
  149. if (pszStr == NULL)
  150. {
  151. m_fFree = FALSE;
  152. return;
  153. }
  154. else
  155. ZeroMemory(pszStr, cchSize);
  156. }
  157. else
  158. {
  159. pszStr = m_szBuf;
  160. ZeroMemory(pszStr, cchSize);
  161. }
  162. }
  163. CAnsiStr::~CAnsiStr()
  164. {
  165. if (m_fFree && (pszStr != NULL))
  166. CoTaskMemFree(pszStr);
  167. }
  168. //------ advpack wrappers --------
  169. // advpack is exclusively ANSI so have to thunk for UNICODE
  170. HRESULT ExtractFilesWrapW(LPCWSTR pszCabName, LPCWSTR pszExpandDir, DWORD dwFlags,
  171. LPCWSTR pszFileList, LPVOID lpReserved, DWORD dwReserved)
  172. {
  173. CAnsiStr astrFileList(pszFileList, NULL);
  174. USES_CONVERSION;
  175. if ((pszFileList != NULL) && (astrFileList.pszStr == NULL))
  176. {
  177. // class memory allocation failed
  178. ASSERT(FALSE);
  179. return E_OUTOFMEMORY;
  180. }
  181. return ExtractFiles(W2CA(pszCabName), W2CA(pszExpandDir), dwFlags,
  182. (LPCSTR)astrFileList.pszStr, lpReserved, dwReserved);
  183. }
  184. HRESULT GetVersionFromFileWrapW(LPWSTR lpszFilename, LPDWORD pdwMSVer, LPDWORD pdwLSVer, BOOL bVersion)
  185. {
  186. USES_CONVERSION;
  187. return GetVersionFromFile(W2A(lpszFilename), pdwMSVer, pdwLSVer, bVersion);
  188. }
  189. HRESULT RunSetupCommandWrapW(HWND hWnd, LPCWSTR szCmdName, LPCWSTR szInfSection, LPCWSTR szDir,
  190. LPCWSTR lpszTitle, HANDLE *phEXE, DWORD dwFlags, LPVOID pvReserved )
  191. {
  192. USES_CONVERSION;
  193. return RunSetupCommand(hWnd, W2CA(szCmdName), W2CA(szInfSection), W2CA(szDir),
  194. W2CA(lpszTitle), phEXE, dwFlags, pvReserved);
  195. }
  196. //------ inseng wrappers --------
  197. // inseng is exclusively ANSI so have to thunk for UNICODE
  198. HRESULT CheckTrustExWrapW(LPCWSTR wszUrl, LPCWSTR wszFilename, HWND hwndForUI, BOOL bShowBadUI, DWORD dwReserved)
  199. {
  200. USES_CONVERSION;
  201. return CheckTrustEx(W2CA(wszUrl), W2CA(wszFilename), hwndForUI, bShowBadUI, dwReserved);
  202. }
  203. // either shlwapi doesn't implement wrappers or their wrappers have limitations on these APIs
  204. //------ kernel32 wrappers --------
  205. // this is the equivalent of GetPrivateProfileString and should only be called if lpAppName
  206. // and/or lpSectionName is NULL. shlwapi's wrappers doesn't handle the series of NULL-terminated
  207. // strings
  208. DWORD GetPrivateProfileStringW_p(LPCWSTR lpAppName, LPCWSTR lpSectionName, LPCWSTR lpDefault,
  209. LPWSTR lpReturnedString, DWORD nSize, LPCWSTR lpFileName)
  210. {
  211. DWORD dwRetLen;
  212. USES_CONVERSION;
  213. // this occurence of GetPrivateProfileStringW is actually wrapped by shlwapi itself so
  214. // you won't actually ever see GetPrivateProfileStringW in the import table for your module
  215. if (IsOS(OS_NT))
  216. dwRetLen = GetPrivateProfileStringW(lpAppName, lpSectionName, lpDefault, lpReturnedString, nSize, lpFileName);
  217. else
  218. {
  219. CAnsiStr astrReturnedString(nSize);
  220. if (astrReturnedString.pszStr == NULL)
  221. {
  222. // class memory allocation failed
  223. ASSERT(FALSE);
  224. return 0;
  225. }
  226. dwRetLen = GetPrivateProfileStringA(W2CA(lpAppName), W2CA(lpSectionName), W2CA(lpDefault),
  227. astrReturnedString.pszStr, nSize, W2CA(lpFileName));
  228. MultiByteToWideChar(CP_ACP, 0, astrReturnedString.pszStr, dwRetLen+1, lpReturnedString, nSize);
  229. // handle possible truncation
  230. if (((lpAppName == NULL) || (lpSectionName == NULL))
  231. && (dwRetLen == (nSize - 2)))
  232. lpReturnedString[nSize - 1] = TEXT('\0');
  233. }
  234. return dwRetLen;
  235. }
  236. DWORD GetPrivateProfileSectionWrapW(LPCWSTR lpAppName, LPWSTR lpReturnedString, DWORD nSize, LPCWSTR lpFileName)
  237. {
  238. DWORD dwRetLen;
  239. USES_CONVERSION;
  240. if (IsOS(OS_NT))
  241. dwRetLen = GetPrivateProfileSectionW(lpAppName, lpReturnedString, nSize, lpFileName);
  242. else
  243. {
  244. CAnsiStr astrReturnedString(nSize);
  245. if (astrReturnedString.pszStr == NULL)
  246. {
  247. // class memory allocation failed
  248. ASSERT(FALSE);
  249. return 0;
  250. }
  251. dwRetLen = GetPrivateProfileSectionA(W2CA(lpAppName), astrReturnedString.pszStr, nSize, W2CA(lpFileName));
  252. MultiByteToWideChar(CP_ACP, 0, astrReturnedString.pszStr, dwRetLen+1, lpReturnedString, nSize);
  253. // null terminate the end of the buffer if size is insufficient
  254. if (dwRetLen == (nSize - 2))
  255. lpReturnedString[nSize - 1] = TEXT('\0');
  256. }
  257. return dwRetLen;
  258. }
  259. BOOL WritePrivateProfileSectionWrapW(LPCWSTR lpAppName, LPCWSTR lpString, LPCWSTR lpFileName)
  260. {
  261. USES_CONVERSION;
  262. if (IsOS(OS_NT))
  263. return WritePrivateProfileSectionW(lpAppName, lpString, lpFileName);
  264. else
  265. {
  266. CAnsiStr astrString(lpString, NULL);
  267. return WritePrivateProfileSectionA(W2CA(lpAppName), astrString.pszStr, W2CA(lpFileName));
  268. }
  269. }
  270. UINT GetDriveTypeWrapW(LPCWSTR lpRootPathName)
  271. {
  272. USES_CONVERSION;
  273. if (IsOS(OS_NT))
  274. return GetDriveTypeW(lpRootPathName);
  275. else
  276. return GetDriveTypeA(W2CA(lpRootPathName));
  277. }
  278. HANDLE OpenMutexWrapW(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName)
  279. {
  280. USES_CONVERSION;
  281. if (IsOS(OS_NT))
  282. return OpenMutexW(dwDesiredAccess, bInheritHandle, lpName);
  283. else
  284. return OpenMutexA(dwDesiredAccess, bInheritHandle, W2CA(lpName));
  285. }
  286. //------ advapi32 wrappers --------
  287. BOOL LookupPrivilegeValueWrapW(LPCWSTR lpSystemName, LPCWSTR lpName, PLUID lpLuid)
  288. {
  289. USES_CONVERSION;
  290. if (IsOS(OS_NT))
  291. return LookupPrivilegeValueW(lpSystemName, lpName, lpLuid);
  292. else
  293. return LookupPrivilegeValueA(W2CA(lpSystemName), W2CA(lpName), lpLuid);
  294. }
  295. LONG RegLoadKeyWrapW(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpFile)
  296. {
  297. USES_CONVERSION;
  298. if (IsOS(OS_NT))
  299. return RegLoadKeyW(hKey, lpSubKey, lpFile);
  300. else
  301. return RegLoadKeyA(hKey, W2CA(lpSubKey), W2CA(lpFile));
  302. }
  303. LONG RegUnLoadKeyWrapW(HKEY hKey, LPCWSTR lpSubKey)
  304. {
  305. USES_CONVERSION;
  306. if (IsOS(OS_NT))
  307. return RegUnLoadKeyW(hKey, lpSubKey);
  308. else
  309. return RegUnLoadKeyA(hKey, W2CA(lpSubKey));
  310. }
  311. LONG RegSaveKeyWrapW(HKEY hKey, LPCWSTR lpFile, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
  312. {
  313. USES_CONVERSION;
  314. if (IsOS(OS_NT))
  315. return RegSaveKeyW(hKey, lpFile, lpSecurityAttributes);
  316. else
  317. return RegSaveKeyA(hKey, W2CA(lpFile), lpSecurityAttributes);
  318. }
  319. //------ shell32 wrappers --------
  320. int SHFileOperationW_p(LPSHFILEOPSTRUCTW lpFileOpW)
  321. {
  322. int iRet;
  323. USES_CONVERSION;
  324. if (IsOS(OS_NT))
  325. iRet = SHFileOperationW(lpFileOpW);
  326. else
  327. {
  328. SHFILEOPSTRUCTA shInfo;
  329. CAnsiStr * pastrIn = NULL;
  330. CAnsiStr * pastrOut = NULL;
  331. ZeroMemory(&shInfo, sizeof(shInfo));
  332. shInfo.fAnyOperationsAborted = lpFileOpW->fAnyOperationsAborted;
  333. shInfo.fFlags = lpFileOpW->fFlags;
  334. shInfo.hNameMappings = lpFileOpW->hNameMappings;
  335. shInfo.hwnd = lpFileOpW->hwnd;
  336. shInfo.lpszProgressTitle = W2A(lpFileOpW->lpszProgressTitle);
  337. shInfo.wFunc = lpFileOpW->wFunc;
  338. pastrIn = new CAnsiStr(lpFileOpW->pFrom, NULL);
  339. if ((pastrIn == NULL) || (pastrIn->pszStr == NULL))
  340. {
  341. // allocation failed
  342. ASSERT(FALSE);
  343. return E_OUTOFMEMORY;
  344. }
  345. shInfo.pFrom = pastrIn->pszStr;
  346. if (lpFileOpW->fFlags & FOF_MULTIDESTFILES)
  347. {
  348. pastrOut = new CAnsiStr(lpFileOpW->pTo, NULL);
  349. if ((pastrOut == NULL) || (pastrOut->pszStr == NULL))
  350. {
  351. // allocation failed
  352. ASSERT(FALSE);
  353. return E_OUTOFMEMORY;
  354. }
  355. shInfo.pTo = pastrOut->pszStr;
  356. }
  357. else
  358. shInfo.pTo = W2A(lpFileOpW->pTo);
  359. iRet = SHFileOperationA(&shInfo);
  360. if (pastrIn != NULL)
  361. delete pastrIn;
  362. if (pastrOut != NULL)
  363. delete pastrOut;
  364. }
  365. return iRet;
  366. }
  367. //------ private util wrappers --------
  368. BOOL RunAndWaitA(LPSTR pszCmd, LPCSTR pcszDir, WORD wShow, LPDWORD lpExitCode /* = NULL */)
  369. {
  370. PROCESS_INFORMATION pi;
  371. STARTUPINFOA stiA;
  372. MSG msg;
  373. ZeroMemory(&stiA, sizeof(stiA));
  374. stiA.cb = sizeof(stiA);
  375. stiA.dwFlags = STARTF_USESHOWWINDOW;
  376. stiA.wShowWindow = wShow;
  377. USES_CONVERSION;
  378. if (!CreateProcessA(NULL, pszCmd, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, pcszDir, &stiA, &pi))
  379. return FALSE;
  380. // wait for the process to finish
  381. while (MsgWaitForMultipleObjects(1, &pi.hProcess, FALSE, INFINITE, QS_ALLINPUT) != WAIT_OBJECT_0)
  382. while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  383. TranslateMessage(&msg);
  384. DispatchMessage(&msg);
  385. }
  386. if (lpExitCode)
  387. GetExitCodeProcess(pi.hProcess, lpExitCode);
  388. CloseHandle(pi.hThread);
  389. CloseHandle(pi.hProcess);
  390. return TRUE;
  391. }
  392. BOOL RunAndWaitW(LPWSTR pwszCmd, LPCWSTR pcwszDir, WORD wShow, LPDWORD lpExitCode /* = NULL */)
  393. {
  394. PROCESS_INFORMATION pi;
  395. STARTUPINFOW stiW;
  396. MSG msg;
  397. ZeroMemory(&stiW, sizeof(stiW));
  398. stiW.cb = sizeof(stiW);
  399. stiW.dwFlags = STARTF_USESHOWWINDOW;
  400. stiW.wShowWindow = wShow;
  401. USES_CONVERSION;
  402. if (!CreateProcessW(NULL, pwszCmd, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, pcwszDir, &stiW, &pi))
  403. return FALSE;
  404. // wait for the process to finish
  405. while (MsgWaitForMultipleObjects(1, &pi.hProcess, FALSE, INFINITE, QS_ALLINPUT) != WAIT_OBJECT_0)
  406. while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  407. TranslateMessage(&msg);
  408. DispatchMessage(&msg);
  409. }
  410. if (lpExitCode)
  411. GetExitCodeProcess(pi.hProcess, lpExitCode);
  412. CloseHandle(pi.hThread);
  413. CloseHandle(pi.hProcess);
  414. return TRUE;
  415. }