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.

532 lines
14 KiB

  1. /*----------------------------------------------------------------------------
  2. / Title;
  3. / misc.cpp
  4. /
  5. / Authors;
  6. / David De Vorchik (daviddv)
  7. /
  8. / Notes;
  9. / Misc functions
  10. /----------------------------------------------------------------------------*/
  11. #include "pch.h"
  12. #include "atlbase.h"
  13. #include <advpub.h> // For REGINSTALL
  14. #pragma hdrstop
  15. /*-----------------------------------------------------------------------------
  16. / GetKeyForCLSID
  17. / --------------
  18. / Given a reference to a CLSID open up the key that represents it.
  19. /
  20. / In:
  21. / clsid = clsid reference
  22. / pSubKey -> name of sub key to be opened
  23. / phkey = receives the newly opened key
  24. /
  25. / Out:
  26. / HRESULT
  27. /----------------------------------------------------------------------------*/
  28. EXTERN_C HRESULT GetKeyForCLSID(REFCLSID clsid, LPCTSTR pSubKey, HKEY* phkey)
  29. {
  30. HRESULT hr;
  31. TCHAR szBuffer[(MAX_PATH*2)+GUIDSTR_MAX];
  32. TCHAR szGuid[GUIDSTR_MAX];
  33. TraceEnter(TRACE_COMMON_MISC, "GetKeyForCLSID");
  34. TraceGUID("clsid", clsid);
  35. Trace(TEXT("pSubKey -%s-"), pSubKey ? pSubKey:TEXT("<none>"));
  36. TraceAssert(phkey);
  37. // - format the CLSID so we can find it in the registry
  38. // - then open it (the client is reponsible for closing it)
  39. *phkey = NULL; // incase we fail
  40. if ( 0 == GetStringFromGUID(clsid, szGuid, ARRAYSIZE(szGuid)) )
  41. ExitGracefully(hr, E_FAIL, "Failed to convert GUID to string");
  42. wsprintf(szBuffer, TEXT("CLSID\\%s"), szGuid);
  43. if ( pSubKey )
  44. {
  45. StrCat(szBuffer, TEXT("\\"));
  46. StrCat(szBuffer, pSubKey);
  47. }
  48. Trace(TEXT("Trying to open -%s-"), szBuffer);
  49. if ( ERROR_SUCCESS != RegOpenKeyEx(HKEY_CLASSES_ROOT, szBuffer, NULL, KEY_READ, phkey) )
  50. ExitGracefully(hr, E_FAIL, "Failed to open key");
  51. hr = S_OK; // success
  52. exit_gracefully:
  53. TraceLeaveResult(hr);
  54. }
  55. /*-----------------------------------------------------------------------------
  56. / GetRealWindowInfo
  57. / -----------------
  58. / Get the window dimensions and client position.
  59. /
  60. / In:
  61. / hwnd = window to enquire about
  62. / pRect -> receives the client position of the window / == NULL
  63. / pSize -> receives the size of the window / == NULL
  64. /
  65. / Out:
  66. / -
  67. /----------------------------------------------------------------------------*/
  68. EXTERN_C HRESULT GetRealWindowInfo(HWND hwnd, LPRECT pRect, LPSIZE pSize)
  69. {
  70. HRESULT hr;
  71. RECT rect;
  72. TraceEnter(TRACE_COMMON_MISC, "GetRealWindowInfo");
  73. if ( !GetWindowRect(hwnd, &rect) )
  74. ExitGracefully(hr, E_FAIL, "Failed to get window rectangles");
  75. MapWindowPoints(NULL, GetParent(hwnd), (LPPOINT)&rect, 2);
  76. if ( pRect )
  77. *pRect = rect;
  78. if ( pSize )
  79. {
  80. pSize->cx = rect.right - rect.left;
  81. pSize->cy = rect.bottom - rect.top;
  82. }
  83. hr = S_OK;
  84. exit_gracefully:
  85. TraceLeaveResult(hr);
  86. }
  87. /*-----------------------------------------------------------------------------
  88. / OffsetWindow
  89. / ------------
  90. / Adjust the position of the given window by the given delta. If the
  91. / delta is 0,0 then this is a NOP.
  92. /
  93. / In:
  94. / hwnd = window to enquire about
  95. / dx, dy = offset to be applied to the window
  96. /
  97. / Out:
  98. / -
  99. /----------------------------------------------------------------------------*/
  100. EXTERN_C VOID OffsetWindow(HWND hwnd, INT dx, INT dy)
  101. {
  102. RECT rect;
  103. TraceEnter(TRACE_COMMON_MISC, "OffsetWindow");
  104. if ( hwnd && (dx || dy) )
  105. {
  106. GetWindowRect(hwnd, &rect);
  107. MapWindowPoints(NULL, GetParent(hwnd), (LPPOINT)&rect, 2);
  108. SetWindowPos(hwnd, NULL, rect.left + dx, rect.top + dy, 0, 0, SWP_NOZORDER|SWP_NOSIZE);
  109. }
  110. TraceLeave();
  111. }
  112. /*-----------------------------------------------------------------------------
  113. / CallRegInstall
  114. / --------------
  115. / Call ADVPACK for the given section of our resource based INF>
  116. /
  117. / In:
  118. / hInstance = resource instance to get REGINST section from
  119. / szSection = section name to invoke
  120. /
  121. / Out:
  122. / HRESULT:
  123. /----------------------------------------------------------------------------*/
  124. EXTERN_C HRESULT CallRegInstall(HINSTANCE hInstance, LPSTR szSection)
  125. {
  126. HRESULT hr = E_FAIL;
  127. HINSTANCE hinstAdvPack = LoadLibrary(TEXT("ADVPACK.DLL"));
  128. TraceEnter(TRACE_COMMON_MISC, "CallRegInstall");
  129. if (hinstAdvPack)
  130. {
  131. REGINSTALL pfnri = (REGINSTALL)GetProcAddress(hinstAdvPack, "RegInstall");
  132. #ifdef UNICODE
  133. if ( pfnri )
  134. {
  135. STRENTRY seReg[] =
  136. {
  137. // These two NT-specific entries must be at the end
  138. { "25", "%SystemRoot%" },
  139. { "11", "%SystemRoot%\\system32" },
  140. };
  141. STRTABLE stReg = { ARRAYSIZE(seReg), seReg };
  142. hr = pfnri(hInstance, szSection, &stReg);
  143. }
  144. #else
  145. if (pfnri)
  146. {
  147. hr = pfnri(hInstance, szSection, NULL);
  148. }
  149. #endif
  150. FreeLibrary(hinstAdvPack);
  151. }
  152. TraceLeaveResult(hr);
  153. }
  154. /*-----------------------------------------------------------------------------
  155. / SetDefButton
  156. / ------------
  157. / Jump through hoops, avoid barking dogs and dice with death all to set
  158. / the default button in a dialog.
  159. /
  160. / In:
  161. / hWnd, idButton = button to set
  162. /
  163. / Out:
  164. / HRESULT:
  165. /----------------------------------------------------------------------------*/
  166. EXTERN_C VOID SetDefButton(HWND hwndDlg, int idButton)
  167. {
  168. LRESULT lr;
  169. LONG style;
  170. TraceEnter(TRACE_COMMON_MISC, "SetDefButton");
  171. if (HIWORD(lr = SendMessage(hwndDlg, DM_GETDEFID, 0, 0)) == DC_HASDEFID)
  172. {
  173. HWND hwndOldDefButton = GetDlgItem(hwndDlg, LOWORD(lr));
  174. style = GetWindowLong(hwndOldDefButton, GWL_STYLE) & ~BS_DEFPUSHBUTTON;
  175. SendMessage (hwndOldDefButton,
  176. BM_SETSTYLE,
  177. MAKEWPARAM(style, 0),
  178. MAKELPARAM(TRUE, 0));
  179. }
  180. SendMessage( hwndDlg, DM_SETDEFID, idButton, 0L );
  181. style = GetWindowLong(GetDlgItem(hwndDlg, idButton), GWL_STYLE)| BS_DEFPUSHBUTTON;
  182. SendMessage( GetDlgItem(hwndDlg, idButton),
  183. BM_SETSTYLE,
  184. MAKEWPARAM( style, 0 ),
  185. MAKELPARAM( TRUE, 0 ));
  186. TraceLeave();
  187. }
  188. /*-----------------------------------------------------------------------------
  189. / Data collection functions
  190. /----------------------------------------------------------------------------*/
  191. /*-----------------------------------------------------------------------------
  192. / AllocStorageMedium
  193. / ------------------
  194. / Allocate a storage medium (validating the clipboard format as required).
  195. /
  196. / In:
  197. / pFmt, pMedium -> describe the allocation
  198. / cbStruct = size of allocation
  199. / ppAlloc -> receives a pointer to the allocation / = NULL
  200. /
  201. / Out:
  202. / HRESULT
  203. /----------------------------------------------------------------------------*/
  204. EXTERN_C HRESULT AllocStorageMedium(FORMATETC* pFmt, STGMEDIUM* pMedium, SIZE_T cbStruct, LPVOID* ppAlloc)
  205. {
  206. HRESULT hr;
  207. TraceEnter(TRACE_COMMON_MISC, "AllocStorageMedium");
  208. TraceAssert(pFmt);
  209. TraceAssert(pMedium);
  210. // Validate parameters
  211. if ( ( cbStruct <= 0 ) || !( pFmt->tymed & TYMED_HGLOBAL ) )
  212. ExitGracefully(hr, E_INVALIDARG, "Zero size stored medium requested or non HGLOBAL");
  213. if ( ( pFmt->ptd ) || !( pFmt->dwAspect & DVASPECT_CONTENT) || !( pFmt->lindex == -1 ) )
  214. ExitGracefully(hr, E_INVALIDARG, "Bad format requested");
  215. // Allocate the medium via GlobalAlloc
  216. pMedium->tymed = TYMED_HGLOBAL;
  217. pMedium->hGlobal = GlobalAlloc(GPTR, cbStruct);
  218. pMedium->pUnkForRelease = NULL;
  219. if ( !pMedium->hGlobal )
  220. ExitGracefully(hr, E_OUTOFMEMORY, "Failed to allocate StgMedium");
  221. hr = S_OK; // success
  222. exit_gracefully:
  223. if ( ppAlloc )
  224. *ppAlloc = SUCCEEDED(hr) ? (LPVOID)pMedium->hGlobal:NULL;
  225. TraceLeaveResult(hr);
  226. }
  227. /*-----------------------------------------------------------------------------
  228. / CopyStorageMedium
  229. / ------------------
  230. / Copies a storage medium (and the data in an HGLOBAL). Only works
  231. / for TYMED_HGLOBAL mediums...
  232. /
  233. / In:
  234. / pMediumDst -> where to copy to...
  235. / pFmt, pMediumSrc -> describe the source
  236. /
  237. / Out:
  238. / HRESULT
  239. /----------------------------------------------------------------------------*/
  240. EXTERN_C HRESULT CopyStorageMedium(FORMATETC* pFmt, STGMEDIUM* pMediumDst, STGMEDIUM* pMediumSrc)
  241. {
  242. HRESULT hr;
  243. LPVOID pSrc, pDst;
  244. HGLOBAL hGlobal;
  245. SIZE_T cbStruct;
  246. TraceEnter(TRACE_COMMON_MISC, "CopyStorageMedium");
  247. if ( !(pFmt->tymed & TYMED_HGLOBAL) )
  248. ExitGracefully(hr, E_INVALIDARG, "Only HGLOBAL mediums suppported to copy");
  249. // stored in a HGLOBAl, therefore get the size, allocate a new storage
  250. // object and copy the data away into it.
  251. cbStruct = GlobalSize((HGLOBAL)pMediumSrc->hGlobal);
  252. hr = AllocStorageMedium(pFmt, pMediumDst, cbStruct, (LPVOID*)&hGlobal);
  253. FailGracefully( hr, "Unable to allocated storage medium" );
  254. *pMediumDst = *pMediumSrc;
  255. pMediumDst->hGlobal = hGlobal;
  256. pSrc = GlobalLock(pMediumSrc->hGlobal);
  257. pDst = GlobalLock(pMediumDst->hGlobal);
  258. CopyMemory(pDst, pSrc, cbStruct);
  259. GlobalUnlock(pMediumSrc->hGlobal);
  260. GlobalUnlock(pMediumDst->hGlobal);
  261. hr = S_OK; // success
  262. exit_gracefully:
  263. TraceLeaveResult(hr);
  264. }
  265. /*-----------------------------------------------------------------------------
  266. / GetStringFromGUID
  267. / -----------------
  268. / Given a GUID convert it to a string.
  269. /
  270. / In:
  271. / rGUID = guid to be converted
  272. / psz, cchMax = buffer to fill
  273. /
  274. / Out:
  275. / NUMBER OF characters
  276. /----------------------------------------------------------------------------*/
  277. static const BYTE c_rgbGuidMap[] = { 3, 2, 1, 0, '-', 5, 4, '-', 7, 6, '-', 8, 9, '-', 10, 11, 12, 13, 14, 15 };
  278. static const TCHAR c_szDigits[] = TEXT("0123456789ABCDEF");
  279. EXTERN_C INT GetStringFromGUID(UNALIGNED REFGUID rguid, LPTSTR psz, INT cchMax)
  280. {
  281. INT i;
  282. const BYTE* pBytes = (const BYTE*)&rguid;
  283. if ( cchMax < GUIDSTR_MAX )
  284. return 0;
  285. #ifdef BIG_ENDIAN
  286. // This is the slow, but portable version
  287. wsprintf(psz, TEXT("{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}"),
  288. rguid->Data1, rguid->Data2, rguid->Data3,
  289. rguid->Data4[0], rguid->Data4[1],
  290. rguid->Data4[2], rguid->Data4[3],
  291. rguid->Data4[4], rguid->Data4[5],
  292. rguid->Data4[6], rguid->Data4[7]);
  293. #else
  294. // The following algorithm is faster than the wsprintf.
  295. *psz++ = TEXT('{');
  296. for (i = 0; i < SIZEOF(c_rgbGuidMap); i++)
  297. {
  298. if (c_rgbGuidMap[i] == TEXT('-')) // don't TEXT() this line
  299. {
  300. *psz++ = TEXT('-');
  301. }
  302. else
  303. {
  304. // Convert a byte-value into a character representation
  305. *psz++ = c_szDigits[ (pBytes[c_rgbGuidMap[i]] & 0xF0) >> 4 ];
  306. *psz++ = c_szDigits[ (pBytes[c_rgbGuidMap[i]] & 0x0F) ];
  307. }
  308. }
  309. *psz++ = TEXT('}');
  310. *psz = TEXT('\0');
  311. #endif /* !BIG_ENDIAN */
  312. return GUIDSTR_MAX;
  313. }
  314. /*-----------------------------------------------------------------------------
  315. / GetGUIDFromString
  316. / -----------------
  317. / Given a string convert it to a GUID.
  318. /
  319. / In:
  320. / psz -> string to be parsed
  321. / rGUID = GUID return into
  322. /
  323. / Out:
  324. / BOOL
  325. /----------------------------------------------------------------------------*/
  326. BOOL _HexStringToDWORD(LPCTSTR * ppsz, DWORD * lpValue, int cDigits, TCHAR chDelim)
  327. {
  328. int ich;
  329. LPCTSTR psz = *ppsz;
  330. DWORD Value = 0;
  331. BOOL fRet = TRUE;
  332. for (ich = 0; ich < cDigits; ich++)
  333. {
  334. TCHAR ch = psz[ich];
  335. if (InRange(ch, TEXT('0'), TEXT('9')))
  336. {
  337. Value = (Value << 4) + ch - TEXT('0');
  338. }
  339. else if ( InRange( (ch |= (TEXT('a')-TEXT('A'))), TEXT('a'), TEXT('f')) )
  340. {
  341. Value = (Value << 4) + ch - TEXT('a') + 10;
  342. }
  343. else
  344. return(FALSE);
  345. }
  346. if (chDelim)
  347. {
  348. fRet = (psz[ich++] == chDelim);
  349. }
  350. *lpValue = Value;
  351. *ppsz = psz+ich;
  352. return fRet;
  353. }
  354. #ifndef UNICODE
  355. EXTERN_C BOOL GetGUIDFromStringW(LPCWSTR psz, GUID* pguid)
  356. {
  357. USES_CONVERSION;
  358. return GetGUIDFromString(W2CT(psz), pguid);
  359. }
  360. #endif
  361. EXTERN_C BOOL GetGUIDFromString(LPCTSTR psz, GUID* pguid)
  362. {
  363. DWORD dw;
  364. if (*psz++ != TEXT('{') /*}*/ )
  365. return FALSE;
  366. if (!_HexStringToDWORD(&psz, &pguid->Data1, SIZEOF(DWORD)*2, TEXT('-')))
  367. return FALSE;
  368. if (!_HexStringToDWORD(&psz, &dw, SIZEOF(WORD)*2, TEXT('-')))
  369. return FALSE;
  370. pguid->Data2 = (WORD)dw;
  371. if (!_HexStringToDWORD(&psz, &dw, SIZEOF(WORD)*2, TEXT('-')))
  372. return FALSE;
  373. pguid->Data3 = (WORD)dw;
  374. if (!_HexStringToDWORD(&psz, &dw, SIZEOF(BYTE)*2, 0))
  375. return FALSE;
  376. pguid->Data4[0] = (BYTE)dw;
  377. if (!_HexStringToDWORD(&psz, &dw, SIZEOF(BYTE)*2, TEXT('-')))
  378. return FALSE;
  379. pguid->Data4[1] = (BYTE)dw;
  380. if (!_HexStringToDWORD(&psz, &dw, SIZEOF(BYTE)*2, 0))
  381. return FALSE;
  382. pguid->Data4[2] = (BYTE)dw;
  383. if (!_HexStringToDWORD(&psz, &dw, SIZEOF(BYTE)*2, 0))
  384. return FALSE;
  385. pguid->Data4[3] = (BYTE)dw;
  386. if (!_HexStringToDWORD(&psz, &dw, SIZEOF(BYTE)*2, 0))
  387. return FALSE;
  388. pguid->Data4[4] = (BYTE)dw;
  389. if (!_HexStringToDWORD(&psz, &dw, SIZEOF(BYTE)*2, 0))
  390. return FALSE;
  391. pguid->Data4[5] = (BYTE)dw;
  392. if (!_HexStringToDWORD(&psz, &dw, SIZEOF(BYTE)*2, 0))
  393. return FALSE;
  394. pguid->Data4[6] = (BYTE)dw;
  395. if (!_HexStringToDWORD(&psz, &dw, SIZEOF(BYTE)*2, /*(*/ TEXT('}')))
  396. return FALSE;
  397. pguid->Data4[7] = (BYTE)dw;
  398. return TRUE;
  399. }
  400. //
  401. // Replacement for LoadStringW that will work on the Win95 downlevel client
  402. //
  403. #ifndef UNICODE
  404. EXTERN_C INT MyLoadStringW(HINSTANCE hInstance, UINT uID, LPWSTR pszBuffer, INT cchBuffer)
  405. {
  406. TCHAR szBuffer[MAX_PATH];
  407. INT cchResult;
  408. cchResult = LoadString(hInstance, uID, szBuffer, ARRAYSIZE(szBuffer));
  409. MultiByteToWideChar(CP_ACP, 0, szBuffer, -1, pszBuffer, cchBuffer);
  410. return cchResult;
  411. }
  412. #endif