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.

1730 lines
44 KiB

  1. /*++
  2. Copyright (c) 1989-2000 Microsoft Corporation
  3. Module Name:
  4. win32base.c
  5. Abstract:
  6. This module implements low level primitives that are win32 compatible.
  7. Author:
  8. clupu created 10/25/2000
  9. Revision History:
  10. --*/
  11. #include "sdbp.h"
  12. #include <time.h>
  13. #include <shlwapi.h>
  14. // Define this for bounds-checked detection of leaks.
  15. // #define BOUNDS_CHECKER_DETECTION
  16. //
  17. // Memory functions
  18. //
  19. void*
  20. SdbAlloc(
  21. IN size_t size // size in bytes to allocate
  22. )
  23. /*++
  24. Return: The pointer allocated.
  25. Desc: Just a wrapper for allocation -- perhaps useful if we move this
  26. code to a non-NTDLL location and need to call differently.
  27. --*/
  28. {
  29. return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
  30. }
  31. void
  32. SdbFree(
  33. IN void* pWhat // ptr allocated with SdbAlloc that should be freed.
  34. )
  35. /*++
  36. Return: The pointer allocated.
  37. Desc: Just a wrapper for deallocation -- perhaps useful if we move this
  38. code to a non-NTDLL location and need to call differently.
  39. --*/
  40. {
  41. HeapFree(GetProcessHeap(), 0, pWhat);
  42. }
  43. HANDLE
  44. SdbpOpenFile(
  45. IN LPCTSTR szPath, // full path of file to open
  46. IN PATH_TYPE eType // must be always DOS_PATH
  47. )
  48. /*++
  49. Return: A handle to the opened file or INVALID_HANDLE_VALUE on failure.
  50. Desc: Just a wrapper for opening an existing file for READ.
  51. --*/
  52. {
  53. HANDLE hFile;
  54. assert(eType == DOS_PATH);
  55. hFile = CreateFile(szPath,
  56. GENERIC_READ,
  57. FILE_SHARE_READ,
  58. NULL,
  59. OPEN_EXISTING,
  60. 0,
  61. NULL);
  62. if (hFile == INVALID_HANDLE_VALUE) {
  63. DBGPRINT((sdlInfo, "SdbpOpenFile", "CreateFileW failed 0x%x.\n", GetLastError()));
  64. }
  65. return hFile;
  66. UNREFERENCED_PARAMETER(eType);
  67. }
  68. void
  69. SdbpQueryAppCompatFlagsForExeID(
  70. IN HKEY hkeyRoot, // the root key (HKLM or HKCU)
  71. IN LPCTSTR pwszExeID, // the exe ID in string format
  72. OUT LPDWORD lpdwFlags // this will contain the flags from the registry.
  73. )
  74. /*++
  75. Return: void.
  76. Desc: BUGBUG
  77. Query registry for compatibility flags. Exe ID is a GUID in string format.
  78. --*/
  79. {
  80. HKEY hkey = NULL;
  81. DWORD type, cbSize, dwFlags = 0;
  82. LONG lRes;
  83. *lpdwFlags = 0;
  84. lRes = RegOpenKey(hkeyRoot, APPCOMPAT_KEY_PATH, &hkey);
  85. if (lRes != ERROR_SUCCESS) {
  86. //
  87. // No key for this ExeID. No big deal.
  88. //
  89. return;
  90. }
  91. cbSize = sizeof(DWORD);
  92. lRes = RegQueryValueEx(hkey, pwszExeID, NULL, &type, (LPBYTE)&dwFlags, &cbSize);
  93. if (lRes != ERROR_SUCCESS || type != REG_DWORD) {
  94. goto cleanup;
  95. }
  96. *lpdwFlags = dwFlags;
  97. cleanup:
  98. RegCloseKey(hkey);
  99. }
  100. BOOL
  101. SdbGetEntryFlags(
  102. IN GUID* pGuid, // the EXE's ID
  103. OUT LPDWORD lpdwFlags // will receive the flags for this EXE
  104. )
  105. /*++
  106. Return: void.
  107. Desc: BUGBUG: comment.
  108. --*/
  109. {
  110. TCHAR szExeID[128];
  111. DWORD dwFlagsMachine = 0, dwFlagsUser = 0;
  112. if (!SdbGUIDToString(pGuid, szExeID, CHARCOUNT(szExeID))) {
  113. DBGPRINT((sdlError, "SdbGetEntryFlags",
  114. "Failed to convert guid to string\n"));
  115. return FALSE;
  116. }
  117. //
  118. // Look in both the local machine and per user keys. Then combine the
  119. // flags.
  120. //
  121. SdbpQueryAppCompatFlagsForExeID(HKEY_LOCAL_MACHINE, szExeID, &dwFlagsMachine);
  122. SdbpQueryAppCompatFlagsForExeID(HKEY_CURRENT_USER, szExeID, &dwFlagsUser);
  123. *lpdwFlags = (dwFlagsMachine | dwFlagsUser);
  124. return TRUE;
  125. }
  126. BOOL
  127. SdbSetEntryFlags(
  128. IN GUID* pGuid, // the EXE's ID
  129. IN DWORD dwFlags // the registry flags for this EXE
  130. )
  131. /*++
  132. Return: void.
  133. Desc: BUGBUG: comment.
  134. --*/
  135. {
  136. TCHAR szExeID[128];
  137. DWORD dwExeFlags;
  138. HKEY hkey = NULL;
  139. LONG lRes;
  140. lRes = RegCreateKey(HKEY_CURRENT_USER, APPCOMPAT_KEY_PATH, &hkey);
  141. if (lRes != ERROR_SUCCESS) {
  142. DBGPRINT((sdlError,
  143. "SdbSetEntryFlags",
  144. "Failed 0x%x to open/create key in HKCU\n",
  145. GetLastError()));
  146. return FALSE;
  147. }
  148. if (!SdbGUIDToString(pGuid, szExeID, CHARCOUNT(szExeID))) {
  149. DBGPRINT((sdlError, "SdbSetEntryFlags",
  150. "Failed to convert GUID to string\n"));
  151. RegCloseKey(hkey);
  152. return FALSE;
  153. }
  154. dwExeFlags = dwFlags;
  155. lRes = RegSetValueEx(hkey,
  156. szExeID,
  157. 0,
  158. REG_DWORD,
  159. (const BYTE*)&dwExeFlags,
  160. sizeof(DWORD));
  161. if (lRes != ERROR_SUCCESS) {
  162. DBGPRINT((sdlError,
  163. "SdbSetEntryFlags",
  164. "Failed 0x%x to set the flags for exe ID.\n",
  165. GetLastError()));
  166. RegCloseKey(hkey);
  167. return FALSE;
  168. }
  169. RegCloseKey(hkey);
  170. return TRUE;
  171. }
  172. VOID
  173. SdbpCleanupUserSDBCache(
  174. IN PSDBCONTEXT pSdbContext
  175. )
  176. {
  177. UNREFERENCED_PARAMETER(pSdbContext);
  178. }
  179. BOOL
  180. SDBAPI
  181. SdbGetNthUserSdb(
  182. IN HSDB hSDB,
  183. IN LPCTSTR szItemName, // file name (foo.exe) or layer name
  184. IN BOOL bLayer, // true if layer
  185. IN OUT LPDWORD pdwIndex, // 0-based index
  186. OUT GUID* pGuidDB // guid of a database to search
  187. )
  188. {
  189. TCHAR szFullKey[512];
  190. LONG lResult;
  191. HKEY hKey = NULL;
  192. DWORD dwNameSize = 0;
  193. DWORD dwDataType;
  194. BOOL bRet = FALSE;
  195. TCHAR szSdbName[MAX_PATH];
  196. DWORD dwIndex = *pdwIndex;
  197. LPTSTR pDot;
  198. if (szItemName == NULL || pGuidDB == NULL || pdwIndex == NULL) {
  199. DBGPRINT((sdlError, "SdbGetNthUserSdb",
  200. "NULL parameter passed for szExeName or pGuidDB or pdwIndex.\n"));
  201. goto out;
  202. }
  203. if (bLayer) {
  204. StringCchPrintf(szFullKey,
  205. CHARCOUNT(szFullKey),
  206. TEXT("%s\\Layers\\%s"),
  207. APPCOMPAT_KEY_PATH_CUSTOM,
  208. szItemName);
  209. } else {
  210. StringCchPrintf(szFullKey,
  211. CHARCOUNT(szFullKey),
  212. TEXT("%s\\%s"),
  213. APPCOMPAT_KEY_PATH_CUSTOM,
  214. szItemName);
  215. }
  216. lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  217. szFullKey,
  218. 0,
  219. KEY_READ,
  220. &hKey);
  221. if (lResult != ERROR_SUCCESS) {
  222. DBGPRINT((sdlInfo, "SdbGetNthUserSdb",
  223. "Failed to open Key \"%s\" Error 0x%x\n", szFullKey, lResult));
  224. goto out;
  225. }
  226. //
  227. // enum all the values please
  228. //
  229. while (TRUE) {
  230. dwNameSize = CHARCOUNT(szSdbName);
  231. lResult = RegEnumValue(hKey,
  232. dwIndex,
  233. szSdbName,
  234. &dwNameSize,
  235. NULL,
  236. &dwDataType,
  237. NULL,
  238. NULL);
  239. dwIndex++;
  240. if (lResult != ERROR_SUCCESS) {
  241. goto out;
  242. }
  243. //
  244. // we have sdb name, convert it to guid
  245. //
  246. pDot = _tcsrchr(szSdbName, TEXT('.'));
  247. if (pDot != NULL) {
  248. *pDot = TEXT('\0'); // old style entry
  249. }
  250. if (SdbGUIDFromString(szSdbName, pGuidDB)) {
  251. //
  252. // we are done
  253. //
  254. break;
  255. }
  256. }
  257. //
  258. // advance the counter if success
  259. //
  260. *pdwIndex = dwIndex;
  261. bRet = TRUE;
  262. out:
  263. if (hKey != NULL) {
  264. RegCloseKey(hKey);
  265. }
  266. return bRet;
  267. UNREFERENCED_PARAMETER(hSDB);
  268. }
  269. //
  270. // These three functions are not needed for Win9x, and are stubbed out here
  271. //
  272. BOOL
  273. SdbGetPermLayerKeys(
  274. IN LPCTSTR szPath,
  275. OUT LPTSTR szLayers,
  276. IN LPDWORD pdwBytes,
  277. IN DWORD dwFlags
  278. )
  279. {
  280. UNREFERENCED_PARAMETER(szPath);
  281. UNREFERENCED_PARAMETER(szLayers);
  282. UNREFERENCED_PARAMETER(pdwBytes);
  283. UNREFERENCED_PARAMETER(dwFlags);
  284. return FALSE;
  285. }
  286. BOOL
  287. SdbSetPermLayerKeys(
  288. IN LPCTSTR szPath,
  289. IN LPCTSTR szLayers,
  290. IN BOOL bMachine
  291. )
  292. {
  293. UNREFERENCED_PARAMETER(szPath);
  294. UNREFERENCED_PARAMETER(szLayers);
  295. UNREFERENCED_PARAMETER(bMachine);
  296. return FALSE;
  297. }
  298. BOOL
  299. SdbDeletePermLayerKeys(
  300. IN LPCTSTR szPath,
  301. IN BOOL bMachine
  302. )
  303. {
  304. UNREFERENCED_PARAMETER(szPath);
  305. UNREFERENCED_PARAMETER(bMachine);
  306. return FALSE;
  307. }
  308. BOOL
  309. SdbpGetLongFileName(
  310. IN LPCTSTR szFullPath, // a full UNC or DOS path & filename, "c:\foo\mylong~1.ext"
  311. OUT LPTSTR szLongFileName, // the long filename portion "mylongfilename.ext"
  312. IN DWORD cchSize // size ((in characters) of szLongFileName
  313. )
  314. /*++
  315. Return: TRUE on success, FALSE otherwise.
  316. Desc: BUGBUG: comment.
  317. --*/
  318. {
  319. HANDLE hFind = INVALID_HANDLE_VALUE;
  320. WIN32_FIND_DATA FindData;
  321. BOOL bReturn = FALSE;
  322. hFind = FindFirstFile(szFullPath, &FindData);
  323. if (hFind == INVALID_HANDLE_VALUE) {
  324. DBGPRINT((sdlError,
  325. "SdbpGetLongFileName",
  326. "FindFirstFile failed, error 0x%x.\n",
  327. GetLastError()));
  328. goto Done;
  329. }
  330. StringCchCopy(szLongFileName, cchSize, FindData.cFileName);
  331. bReturn = TRUE;
  332. Done:
  333. if (hFind != INVALID_HANDLE_VALUE) {
  334. FindClose(hFind);
  335. }
  336. return bReturn;
  337. }
  338. void
  339. SdbpGetWinDir(
  340. OUT LPTSTR pszDir, // will contain the %windir% path.
  341. IN DWORD cchSize
  342. )
  343. /*++
  344. Return: void.
  345. Desc: This is a wrapper function to get the windows directory.
  346. --*/
  347. {
  348. UINT cch;
  349. //
  350. // BUGBUG: This will only work properly on non-TS system.
  351. // On TS we need to use GetSystemWindowsDirectory instead.
  352. //
  353. cch = GetWindowsDirectory(pszDir, cchSize);
  354. if (cch == 0) {
  355. *pszDir = 0;
  356. }
  357. }
  358. void
  359. SdbpGetAppPatchDir(
  360. IN HSDB hSDB,
  361. OUT LPTSTR szAppPatchPath, // will contain %windir%\AppPatch path
  362. IN DWORD cchSize // size of szAppPatchPath (in characters)
  363. )
  364. /*++
  365. Return: void.
  366. Desc: This is a wrapper function to get the %windir%\AppPatch directory.
  367. --*/
  368. {
  369. PSDBCONTEXT pContext = (PSDBCONTEXT)hSDB;
  370. UINT cch;
  371. //
  372. // BUGBUG: This will only work properly on non-TS system.
  373. // On TS we need to use GetSystemWindowsDirectory instead.
  374. //
  375. cch = GetWindowsDirectory(szAppPatchPath, cchSize);
  376. //
  377. // Make sure the path doesn't end with '\\'
  378. //
  379. if (cch > 0 && _T('\\') == szAppPatchPath[cch - 1]) {
  380. szAppPatchPath[cch - 1] = _T('\0');
  381. }
  382. if (pContext != NULL && pContext->uExeType == IMAGE_FILE_MACHINE_IA64) {
  383. StringCchCat(szAppPatchPath, cchSize, _T("\\AppPatch\\IA64"));
  384. } else {
  385. StringCchCat(szAppPatchPath, cchSize, _T("\\AppPatch"));
  386. }
  387. }
  388. void
  389. SdbpGetCurrentTime(
  390. OUT LPSYSTEMTIME lpTime // will contain the local time
  391. )
  392. /*++
  393. Return: void.
  394. Desc: This is a wrapper function to get the local time.
  395. --*/
  396. {
  397. GetLocalTime(lpTime);
  398. }
  399. NTSTATUS
  400. SdbpGetEnvVar(
  401. IN LPCTSTR pEnvironment,
  402. IN LPCTSTR pszVariableName,
  403. OUT LPTSTR pszVariableValue,
  404. OUT LPDWORD pdwBufferSize
  405. )
  406. /*++
  407. Return: BUGBUG: ?
  408. Desc: Retrieves the value of the specified environment variable.
  409. --*/
  410. {
  411. DWORD dwLength;
  412. DWORD dwBufferSize = 0;
  413. NTSTATUS Status;
  414. assert(pEnvironment == NULL);
  415. if (pdwBufferSize && pszVariableValue) {
  416. dwBufferSize = *pdwBufferSize;
  417. }
  418. dwLength = GetEnvironmentVariable(pszVariableName, (LPTSTR)pszVariableValue, dwBufferSize);
  419. if (dwLength == 0) {
  420. //
  421. // The variable was not found. Just return.
  422. //
  423. return STATUS_VARIABLE_NOT_FOUND;
  424. }
  425. if (dwLength >= dwBufferSize) {
  426. Status = STATUS_BUFFER_TOO_SMALL;
  427. } else {
  428. Status = STATUS_SUCCESS;
  429. }
  430. if (pdwBufferSize != NULL) {
  431. *pdwBufferSize = dwLength;
  432. }
  433. return Status;
  434. UNREFERENCED_PARAMETER(pEnvironment);
  435. }
  436. LPSTR
  437. SdbpFastUnicodeToAnsi(
  438. IN PDB pdb, // pointer to the database
  439. IN LPCWSTR pwszSrc, // String to convert
  440. IN TAG_TYPE ttTag, // tag type from which pwszSrc was obtained,
  441. // either STRINGREF or STRING
  442. IN DWORD dwRef // tagid or string's stringref
  443. )
  444. /*++
  445. Return: The pointer to the ANSI string in the hash table.
  446. Desc: This function converts a UNICODE string to ANSI and stores it in a hash
  447. table. It then returns the pointer to the ANSI string in the hash table.
  448. Subsequent calls trying to convert a string that has been previously
  449. converted will be very fast.
  450. --*/
  451. {
  452. LPSTR pszDest = NULL;
  453. PSTRHASH pHash = NULL;
  454. INT nSize;
  455. LPSTR pszBuffer = NULL;
  456. if (pwszSrc == NULL) {
  457. goto Done;
  458. }
  459. //
  460. // See if this string comes from the stringtable or it is in-place.
  461. //
  462. switch (ttTag) {
  463. case TAG_TYPE_STRING:
  464. if (pdb->pHashStringBody == NULL) {
  465. pdb->pHashStringBody = HashCreate();
  466. }
  467. pHash = pdb->pHashStringBody;
  468. break;
  469. case TAG_TYPE_STRINGREF:
  470. if (pdb->pHashStringTable == NULL) {
  471. pdb->pHashStringTable = HashCreate();
  472. }
  473. pHash = pdb->pHashStringTable;
  474. break;
  475. default:
  476. DBGPRINT((sdlError,
  477. "SdbpFastUnicodeToAnsi",
  478. "ttTag 0x%x should be STRING or STRINGREF\n",
  479. ttTag));
  480. assert(FALSE);
  481. break;
  482. }
  483. if (pHash == NULL) {
  484. DBGPRINT((sdlError,
  485. "SdbpFastUnicodeToAnsi",
  486. "Pointer to hash is invalid, tag type 0x%x\n",
  487. ttTag));
  488. return NULL;
  489. }
  490. pszDest = HashFindStringByRef(pHash, dwRef);
  491. if (pszDest == NULL) {
  492. //
  493. // Convert the string to ANSI. Do it in 2 steps to find
  494. // the required size first.
  495. //
  496. nSize = WideCharToMultiByte(CP_OEMCP,
  497. 0,
  498. pwszSrc,
  499. -1,
  500. NULL,
  501. 0,
  502. NULL,
  503. NULL);
  504. if (nSize == 0) {
  505. DBGPRINT((sdlError,
  506. "SdbpFastUnicodeToAnsi",
  507. "WideCharToMultiByte failed 0x%x.\n",
  508. GetLastError()));
  509. goto Done;
  510. }
  511. STACK_ALLOC(pszBuffer, nSize); // size is in BYTES
  512. if (pszBuffer == NULL) {
  513. DBGPRINT((sdlError,
  514. "SdbpFastUnicodeToAnsi",
  515. "Failed to allocate 0x%x bytes on the stack.\n",
  516. nSize));
  517. goto Done;
  518. }
  519. nSize = WideCharToMultiByte(CP_OEMCP,
  520. 0,
  521. pwszSrc,
  522. -1,
  523. pszBuffer,
  524. nSize,
  525. NULL,
  526. NULL);
  527. if (nSize == 0) {
  528. DBGPRINT((sdlError,
  529. "UnicodeStringToString",
  530. "WideCharToMultiByte failed with buffer Error = 0x%lx\n",
  531. GetLastError()));
  532. goto Done;
  533. }
  534. //
  535. // Now we are ready to store the string in the hash table.
  536. //
  537. pszDest = HashAddStringByRef(pHash, pszBuffer, dwRef);
  538. }
  539. Done:
  540. if (pszBuffer != NULL) {
  541. STACK_FREE(pszBuffer);
  542. }
  543. return pszDest;
  544. }
  545. BOOL
  546. SdbpMapFile(
  547. IN HANDLE hFile, // handle to the open file (this is done previously)
  548. OUT PIMAGEFILEDATA pImageData // stores the mapping info
  549. )
  550. /*++
  551. Return: TRUE on success, FALSE otherwise.
  552. Desc: This function maps the view of a file in memory so that access operations
  553. on that file are faster.
  554. --*/
  555. {
  556. HANDLE hSection = NULL;
  557. PVOID pBase = NULL;
  558. LARGE_INTEGER liFileSize;
  559. MEMORY_BASIC_INFORMATION MemoryInfo;
  560. if (hFile == INVALID_HANDLE_VALUE) {
  561. DBGPRINT((sdlError,
  562. "SdbpMapFile",
  563. "Invalid parameter.\n"));
  564. return FALSE;
  565. }
  566. liFileSize.LowPart = GetFileSize(hFile, (LPDWORD)&liFileSize.HighPart);
  567. if (liFileSize.LowPart == (DWORD)-1) {
  568. DWORD dwError = GetLastError();
  569. if (dwError != NO_ERROR) {
  570. DBGPRINT((sdlError, "SdbpMapFile", "GetFileSize failed with 0x%x.\n", dwError));
  571. return FALSE;
  572. }
  573. }
  574. hSection = CreateFileMapping(hFile,
  575. NULL, // no inheritance
  576. PAGE_READONLY | SEC_COMMIT,
  577. 0,
  578. 0,
  579. NULL);
  580. if (hSection == NULL) {
  581. DBGPRINT((sdlError,
  582. "SdbpMapFile",
  583. "CreateFileMapping failed with 0x%x.\n",
  584. GetLastError()));
  585. return FALSE;
  586. }
  587. //
  588. // Now map the view.
  589. //
  590. pBase = MapViewOfFile(hSection,
  591. FILE_MAP_READ,
  592. 0,
  593. 0,
  594. 0);
  595. if (pBase == NULL) {
  596. CloseHandle(hSection);
  597. DBGPRINT((sdlError,
  598. "SdbpMapFile",
  599. "MapViewOfFile failed with 0x%x.\n",
  600. GetLastError()));
  601. return FALSE;
  602. }
  603. //
  604. // Why do you need both FileSize and ViewSize ?
  605. // Both FileSize and ViewSize are used in various places
  606. // need to re-examine why and how they're used - BUGBUG
  607. //
  608. VirtualQuery(pBase, &MemoryInfo, sizeof(MemoryInfo));
  609. pImageData->hFile = hFile;
  610. pImageData->hSection = hSection;
  611. pImageData->pBase = pBase;
  612. pImageData->ViewSize = MemoryInfo.RegionSize;
  613. pImageData->FileSize = liFileSize.QuadPart;
  614. return TRUE;
  615. }
  616. BOOL
  617. SdbpUnmapFile(
  618. IN PIMAGEFILEDATA pImageData // mapping info
  619. )
  620. /*++
  621. Return: TRUE on success, FALSE otherwise.
  622. Desc: This function unmaps the view of a file.
  623. --*/
  624. {
  625. if (pImageData->pBase) {
  626. UnmapViewOfFile(pImageData->pBase);
  627. pImageData->pBase = NULL;
  628. }
  629. if (pImageData->hSection) {
  630. CloseHandle(pImageData->hSection);
  631. pImageData->hSection = NULL;
  632. }
  633. pImageData->hFile = INVALID_HANDLE_VALUE;
  634. return TRUE;
  635. }
  636. LPTSTR
  637. SdbpDuplicateString(
  638. IN LPCTSTR pszSrc // pointer to the string to be duplicated
  639. )
  640. /*++
  641. Return: A pointer to the allocated duplicated string.
  642. Desc: Duplicates a string by allocating a copy from the heap.
  643. --*/
  644. {
  645. LPTSTR pszDest = NULL;
  646. int nSize;
  647. assert(pszSrc != NULL);
  648. nSize = (int)(_tcslen(pszSrc) + 1) * sizeof(TCHAR);
  649. pszDest = (LPTSTR)SdbAlloc(nSize);
  650. if (pszDest == NULL) {
  651. DBGPRINT((sdlError,
  652. "SdbpDuplicateString",
  653. "Failed to allocate %d bytes.\n",
  654. nSize));
  655. return NULL;
  656. }
  657. RtlMoveMemory(pszDest, pszSrc, nSize);
  658. return pszDest;
  659. }
  660. BOOL
  661. SdbpReadStringToAnsi(
  662. IN PDB pdb,
  663. IN TAGID tiWhich,
  664. OUT LPSTR pszBuffer,
  665. IN DWORD dwBufferSize
  666. )
  667. /*++
  668. Return: TRUE on success, FALSE otherwise.
  669. Desc: Reads a string from the database and converts it to ANSI.
  670. --*/
  671. {
  672. WCHAR* pData;
  673. INT nch;
  674. pData = (WCHAR*)SdbpGetMappedTagData(pdb, tiWhich);
  675. if (pData == NULL) {
  676. DBGPRINT((sdlError,
  677. "SdbpReadStringToAnsi",
  678. "SdbpGetMappedTagData failed for TAGID 0x%x.\n",
  679. tiWhich));
  680. return FALSE;
  681. }
  682. nch = WideCharToMultiByte(CP_OEMCP,
  683. 0,
  684. pData,
  685. -1,
  686. pszBuffer,
  687. dwBufferSize * sizeof(TCHAR),
  688. NULL,
  689. NULL);
  690. if (nch == 0) {
  691. DBGPRINT((sdlError,
  692. "SdbpReadStringToAnsi",
  693. "WideCharToMultiByte failed with 0x%x.\n",
  694. GetLastError()));
  695. return FALSE;
  696. }
  697. return TRUE;
  698. }
  699. DWORD
  700. SdbpGetFileSize(
  701. IN HANDLE hFile // handle to the file to check the size of
  702. )
  703. /*++
  704. Return: The size of the file or 0 on failure.
  705. Desc: Gets the lower DWORD of the size of a file -- only
  706. works accurately with files smaller than 2GB.
  707. In general, since we're only interested in matching, we're
  708. fine just matching the least significant DWORD of the file size.
  709. --*/
  710. {
  711. return GetFileSize(hFile, NULL);
  712. }
  713. BOOL
  714. SdbpQueryFileDirectoryAttributes(
  715. IN LPCTSTR FilePath,
  716. OUT PFILEDIRECTORYATTRIBUTES pFileDirectoryAttributes
  717. )
  718. /*++
  719. Return: TRUE on success, FALSE otherwise.
  720. Desc: BUGBUG: ?
  721. --*/
  722. {
  723. WIN32_FIND_DATA FindData;
  724. HANDLE hFind;
  725. ZeroMemory(pFileDirectoryAttributes, sizeof(*pFileDirectoryAttributes));
  726. hFind = FindFirstFile(FilePath, &FindData);
  727. if (hFind == INVALID_HANDLE_VALUE) {
  728. DBGPRINT((sdlError,
  729. "SdbpQueryFileDirectoryAttributes",
  730. "FindFirstFile failed with 0x%x.\n",
  731. GetLastError()));
  732. return FALSE;
  733. }
  734. //
  735. // Make sure we are not checking vlfs.
  736. //
  737. if (FindData.nFileSizeHigh != 0) {
  738. DBGPRINT((sdlError,
  739. "SdbpQueryFileDirectoryAttributes",
  740. "Checking vlf files (0x%x 0x%x) is not supported\n",
  741. FindData.nFileSizeHigh,
  742. FindData.nFileSizeLow));
  743. return FALSE;
  744. }
  745. pFileDirectoryAttributes->dwFlags |= FDA_FILESIZE;
  746. pFileDirectoryAttributes->dwFileSizeHigh = FindData.nFileSizeHigh;
  747. pFileDirectoryAttributes->dwFileSizeLow = FindData.nFileSizeLow;
  748. FindClose(hFind);
  749. return TRUE;
  750. }
  751. BOOL
  752. SdbpDoesFileExists(
  753. IN LPCTSTR pszFilePath // the full path of the file
  754. )
  755. /*++
  756. Return: TRUE on success, FALSE otherwise.
  757. Desc: Checks if the specified file exists.
  758. --*/
  759. {
  760. DWORD dwAttributes;
  761. dwAttributes = GetFileAttributes(pszFilePath);
  762. return (dwAttributes != (DWORD)-1);
  763. }
  764. BOOL
  765. SdbpGet16BitDescription(
  766. OUT LPTSTR* ppszDescription,
  767. IN PIMAGEFILEDATA pImageData
  768. )
  769. /*++
  770. Return: TRUE on success, FALSE otherwise.
  771. Desc: BUGBUG: ?
  772. --*/
  773. {
  774. BOOL bSuccess;
  775. CHAR szBuffer[256];
  776. LPTSTR pszDescription = NULL;
  777. bSuccess = SdbpQuery16BitDescription(szBuffer, pImageData);
  778. if (bSuccess) {
  779. pszDescription = SdbpDuplicateString(szBuffer);
  780. *ppszDescription = pszDescription;
  781. }
  782. return (pszDescription != NULL);
  783. }
  784. BOOL
  785. SdbpGet16BitModuleName(
  786. OUT LPTSTR* ppszModuleName,
  787. IN PIMAGEFILEDATA pImageData
  788. )
  789. /*++
  790. Return: TRUE on success, FALSE otherwise.
  791. Desc: BUGBUG: ?
  792. --*/
  793. {
  794. BOOL bSuccess;
  795. CHAR szBuffer[256];
  796. LPTSTR pszModuleName = NULL;
  797. bSuccess = SdbpQuery16BitModuleName(szBuffer, pImageData);
  798. if (bSuccess) {
  799. pszModuleName = SdbpDuplicateString(szBuffer);
  800. *ppszModuleName = pszModuleName;
  801. }
  802. return (pszModuleName != NULL);
  803. }
  804. PVOID
  805. SdbGetFileInfo(
  806. IN HSDB hSDB,
  807. IN LPCTSTR pszFilePath,
  808. IN HANDLE hFile OPTIONAL,
  809. IN LPVOID pImageBase OPTIONAL,
  810. IN DWORD dwImageSize OPTIONAL,
  811. IN BOOL bNoCache
  812. )
  813. /*++
  814. Return: BUGBUG: ?
  815. Desc: BUGBUG: ?
  816. --*/
  817. {
  818. PSDBCONTEXT pContext = (PSDBCONTEXT)hSDB;
  819. LPTSTR FullPath;
  820. PFILEINFO pFileInfo = NULL;
  821. DWORD nBufferLength;
  822. DWORD cch;
  823. //
  824. // See if we have info on this file. Get the full path first.
  825. //
  826. cch = GetFullPathName(pszFilePath, 0, NULL, NULL);
  827. if (cch == 0) {
  828. DBGPRINT((sdlError,
  829. "GetFileInfo",
  830. "GetFullPathName failed for \"%s\" with 0x%x.\n",
  831. pszFilePath,
  832. GetLastError()));
  833. return NULL;
  834. }
  835. nBufferLength = (cch + 1) * sizeof(TCHAR);
  836. STACK_ALLOC(FullPath, nBufferLength);
  837. if (FullPath == NULL) {
  838. DBGPRINT((sdlError,
  839. "GetFileInfo",
  840. "Failed to allocate %d bytes on the stack for full path.\n",
  841. nBufferLength));
  842. return NULL;
  843. }
  844. cch = GetFullPathName(pszFilePath,
  845. nBufferLength,
  846. FullPath,
  847. NULL);
  848. assert(cch <= nBufferLength);
  849. if (cch > nBufferLength || cch == 0) {
  850. DBGPRINT((sdlError,
  851. "GetFileInfo",
  852. "GetFullPathName failed for \"%s\" with 0x%x.\n",
  853. pszFilePath,
  854. GetLastError()));
  855. STACK_FREE(FullPath);
  856. return NULL;
  857. }
  858. if (!bNoCache) {
  859. pFileInfo = FindFileInfo(pContext, FullPath);
  860. }
  861. if (pFileInfo == NULL) {
  862. if (SdbpDoesFileExists(FullPath)) {
  863. pFileInfo = CreateFileInfo(pContext,
  864. FullPath,
  865. cch,
  866. hFile,
  867. pImageBase,
  868. dwImageSize,
  869. bNoCache);
  870. }
  871. }
  872. STACK_FREE(FullPath);
  873. return (PVOID)pFileInfo;
  874. }
  875. int
  876. GetShimDbgLevel(
  877. void
  878. )
  879. {
  880. TCHAR szDebugLevel[128];
  881. DWORD cch;
  882. INT iShimDebugLevel = 0;
  883. cch = GetEnvironmentVariable(TEXT("SHIM_DEBUG_LEVEL"),
  884. szDebugLevel,
  885. CHARCOUNT(szDebugLevel));
  886. if (cch != 0) {
  887. iShimDebugLevel = (int)_tcstol(szDebugLevel, NULL, 0);
  888. }
  889. return iShimDebugLevel;
  890. }
  891. BOOL
  892. SdbpWriteBitsToFile(
  893. LPCTSTR pszFile,
  894. PBYTE pBuffer,
  895. DWORD dwSize
  896. )
  897. /*++
  898. Return: TRUE on success, FALSE otherwise.
  899. Desc: Self explanatory.
  900. --*/
  901. {
  902. HANDLE hFile = INVALID_HANDLE_VALUE;
  903. BOOL bReturn = FALSE;
  904. DWORD dwBytesWritten;
  905. hFile = CreateFile(pszFile,
  906. GENERIC_READ | GENERIC_WRITE,
  907. 0, // no sharing
  908. NULL,
  909. CREATE_ALWAYS,
  910. FILE_ATTRIBUTE_NORMAL,
  911. NULL);
  912. if (hFile == INVALID_HANDLE_VALUE) {
  913. DBGPRINT((sdlError, "SdbpWriteBitsToFile",
  914. "Failed to create file \"%s\" Error 0x%lx.\n", pszFile, GetLastError()));
  915. goto cleanup;
  916. }
  917. if (!WriteFile(hFile, pBuffer, dwSize, &dwBytesWritten, NULL)) {
  918. DBGPRINT((sdlError, "SdbpWriteBitsToFile",
  919. "Failed to write bits to file \"%s\" Error 0x%lx\n", pszFile, GetLastError()));
  920. goto cleanup;
  921. }
  922. bReturn = TRUE;
  923. cleanup:
  924. if (hFile != INVALID_HANDLE_VALUE) {
  925. CloseHandle(hFile);
  926. }
  927. return bReturn;
  928. }
  929. /***
  930. * void _resetstkoflw(void) - Recovers from Stack Overflow
  931. *
  932. * Purpose:
  933. * Sets the guard page to its position before the stack overflow.
  934. *
  935. *******************************************************************************/
  936. VOID
  937. SdbResetStackOverflow(
  938. VOID
  939. )
  940. {
  941. LPBYTE pStack, pGuard, pStackBase, pCommitBase;
  942. MEMORY_BASIC_INFORMATION mbi;
  943. SYSTEM_INFO si;
  944. DWORD PageSize;
  945. // Use alloca() to get the current stack pointer
  946. pStack = _alloca(1);
  947. // Find the base of the stack.
  948. VirtualQuery(pStack, &mbi, sizeof mbi);
  949. pStackBase = mbi.AllocationBase;
  950. VirtualQuery(pStackBase, &mbi, sizeof mbi);
  951. if (mbi.State & MEM_RESERVE) {
  952. pCommitBase = (LPBYTE)mbi.AllocationBase + mbi.RegionSize;
  953. VirtualQuery(pCommitBase, &mbi, sizeof mbi);
  954. } else {
  955. pCommitBase = pStackBase;
  956. }
  957. //
  958. // Find the page just below where stack pointer currently points.
  959. //
  960. GetSystemInfo(&si);
  961. PageSize = si.dwPageSize;
  962. pGuard = (LPBYTE) (((DWORD_PTR)pStack & ~(DWORD_PTR)(PageSize -1)) - PageSize);
  963. if ( pGuard < pStackBase) {
  964. //
  965. // We can't save this
  966. //
  967. return;
  968. }
  969. if (pGuard > pStackBase) {
  970. VirtualFree(pStackBase, pGuard -pStackBase, MEM_DECOMMIT);
  971. }
  972. VirtualAlloc(pGuard, PageSize, MEM_COMMIT, PAGE_READWRITE);
  973. VirtualProtect(pGuard, PageSize, PAGE_READWRITE | PAGE_GUARD, &PageSize);
  974. }
  975. DWORD
  976. SdbExpandEnvironmentStrings(
  977. IN LPCTSTR lpSrc,
  978. OUT LPTSTR lpDst,
  979. IN DWORD nSize)
  980. {
  981. return ExpandEnvironmentStrings(lpSrc, lpDst, nSize);
  982. }
  983. TCHAR g_szDatabasePath[] = TEXT("DatabasePath");
  984. TCHAR g_szDatabaseType[] = TEXT("DatabaseType");
  985. TCHAR g_szDatabaseDescription[] = TEXT("DatabaseDescription");
  986. BOOL
  987. SDBAPI
  988. SdbGetDatabaseRegPath(
  989. IN GUID* pguidDB,
  990. OUT LPTSTR pszDatabasePath,
  991. IN DWORD dwBufferSize // size (in tchars) of the buffer
  992. )
  993. {
  994. TCHAR szDatabaseID[64];
  995. HRESULT hr;
  996. SdbGUIDToString(pguidDB, szDatabaseID, CHARCOUNT(szDatabaseID));
  997. hr = StringCchPrintf(pszDatabasePath,
  998. (size_t)dwBufferSize,
  999. TEXT("%s\\%s"),
  1000. APPCOMPAT_KEY_PATH_INSTALLEDSDB,
  1001. szDatabaseID);
  1002. return (hr == S_OK);
  1003. }
  1004. BOOL
  1005. SDBAPI
  1006. SdbUnregisterDatabase(
  1007. IN GUID* pguidDB
  1008. )
  1009. /*++
  1010. Unregisters a database so it's no longer available.
  1011. --*/
  1012. {
  1013. TCHAR szFullKey[512];
  1014. //
  1015. // Form the key
  1016. //
  1017. if (!SdbGetDatabaseRegPath(pguidDB, szFullKey, CHARCOUNT(szFullKey))) {
  1018. DBGPRINT((sdlError, "SdbUnregisterDatabase", "Failed to get database key path\n"));
  1019. return FALSE;
  1020. }
  1021. return (SHDeleteKey(HKEY_LOCAL_MACHINE, szFullKey) == ERROR_SUCCESS);
  1022. }
  1023. BOOL
  1024. SDBAPI
  1025. SdbRegisterDatabase(
  1026. IN LPCTSTR pszDatabasePath,
  1027. IN DWORD dwDatabaseType
  1028. )
  1029. /*++
  1030. Registers any given database so that it is "known" to our database lookup apis
  1031. Caller must ensure that appcompatflags registry entry exists
  1032. If the function fails -- the caller should try to cleanup the mess using SdbUnregisterDatabase
  1033. --*/
  1034. {
  1035. // first we write the database path
  1036. PSDBDATABASEINFO pDbInfo = NULL;
  1037. BOOL bReturn = FALSE;
  1038. DWORD dwPathLength;
  1039. DWORD dwLength;
  1040. LPTSTR pszFullPath = NULL;
  1041. TCHAR szDatabaseID[64]; // sufficient for guid
  1042. LONG lResult;
  1043. HKEY hKeyInstalledSDB = NULL;
  1044. HKEY hKey = NULL;
  1045. BOOL bExpandSZ = FALSE;
  1046. BOOL bFreeFullPath = FALSE;
  1047. //
  1048. // see if we need to expand some strings...
  1049. //
  1050. if (_tcschr(pszDatabasePath, TEXT('%')) != NULL) {
  1051. bExpandSZ = TRUE;
  1052. dwPathLength = ExpandEnvironmentStrings(pszDatabasePath, NULL, 0);
  1053. if (dwPathLength == 0) {
  1054. DBGPRINT((sdlError, "SdbRegisterDatabase",
  1055. "Failed to expand environment strings for \"%s\" Error 0x%lx\n",
  1056. pszDatabasePath, GetLastError()));
  1057. return FALSE;
  1058. }
  1059. pszFullPath = SdbAlloc(dwPathLength * sizeof(WCHAR));
  1060. if (pszFullPath == NULL) {
  1061. DBGPRINT((sdlError, "SdbRegisterDatabase",
  1062. "Failed to allocate 0x%lx bytes for the path buffer \"%s\"\n",
  1063. dwPathLength, pszDatabasePath));
  1064. return FALSE;
  1065. }
  1066. bFreeFullPath = TRUE;
  1067. dwLength = ExpandEnvironmentStrings(pszDatabasePath, pszFullPath, dwPathLength);
  1068. if (dwLength == 0 || dwLength > dwPathLength) {
  1069. DBGPRINT((sdlError, "SdbRegisterDatabase",
  1070. "Failed to expand environment strings for \"%s\" Length 0x%lx Return value 0x%lx Error 0x%lx\n",
  1071. pszDatabasePath, dwPathLength, dwLength, GetLastError()));
  1072. goto HandleError;
  1073. }
  1074. } else { // this path does not need expansion
  1075. pszFullPath = (LPTSTR)pszDatabasePath;
  1076. }
  1077. if (!SdbGetDatabaseInformationByName(pszFullPath, &pDbInfo)) {
  1078. DBGPRINT((sdlError, "SdbRegisterDatabase",
  1079. "Cannot obtain database information for \"%s\"\n", pszFullPath));
  1080. goto HandleError;
  1081. }
  1082. if (!(pDbInfo->dwFlags & DBINFO_GUID_VALID)) {
  1083. DBGPRINT((sdlError, "SdbRegisterDatabase",
  1084. "Cannot register database with no id \"%s\"\n", pszDatabasePath));
  1085. goto HandleError;
  1086. }
  1087. //
  1088. // convert the guid into the string, returns true always
  1089. //
  1090. SdbGUIDToString(&pDbInfo->guidDB, szDatabaseID, CHARCOUNT(szDatabaseID));
  1091. //
  1092. // now that we have database information - create entry
  1093. //
  1094. lResult = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  1095. APPCOMPAT_KEY_PATH_INSTALLEDSDB,
  1096. 0,
  1097. NULL,
  1098. REG_OPTION_NON_VOLATILE,
  1099. KEY_WRITE|KEY_READ,
  1100. NULL,
  1101. &hKeyInstalledSDB,
  1102. NULL);
  1103. if (lResult != ERROR_SUCCESS) {
  1104. DBGPRINT((sdlError, "SdbRegisterDatabase",
  1105. "Failed to create key \"%s\" error 0x%lx\n", APPCOMPAT_KEY_PATH_INSTALLEDSDB, lResult));
  1106. goto HandleError;
  1107. }
  1108. assert(hKeyInstalledSDB != NULL);
  1109. //
  1110. // now create the key for the existing database
  1111. //
  1112. lResult = RegCreateKeyEx(hKeyInstalledSDB, // subkey
  1113. szDatabaseID,
  1114. 0,
  1115. NULL,
  1116. REG_OPTION_NON_VOLATILE,
  1117. KEY_WRITE|KEY_READ,
  1118. NULL,
  1119. &hKey,
  1120. NULL);
  1121. if (lResult != ERROR_SUCCESS) {
  1122. DBGPRINT((sdlError, "SdbRegisterDatabase",
  1123. "Failed to create key \"%s\" error 0x%lx\n", szDatabaseID, lResult));
  1124. goto HandleError;
  1125. }
  1126. assert(hKey != NULL);
  1127. //
  1128. // set values for this database
  1129. //
  1130. lResult = RegSetValueEx(hKey,
  1131. g_szDatabasePath,
  1132. 0,
  1133. bExpandSZ ? REG_EXPAND_SZ : REG_SZ,
  1134. (PBYTE)pszFullPath,
  1135. (DWORD)(_tcslen(pszFullPath) + 1) * sizeof(*pszFullPath));
  1136. if (lResult != ERROR_SUCCESS) {
  1137. DBGPRINT((sdlError, "SdbRegisterDatabase",
  1138. "Failed to set value \"%s\" to \"%s\" Error 0x%lx\n",
  1139. g_szDatabasePath, pszFullPath, lResult));
  1140. goto HandleError;
  1141. }
  1142. lResult = RegSetValueEx(hKey,
  1143. g_szDatabaseType,
  1144. 0,
  1145. REG_DWORD,
  1146. (PBYTE)&dwDatabaseType,
  1147. sizeof(dwDatabaseType));
  1148. if (lResult != ERROR_SUCCESS) {
  1149. DBGPRINT((sdlError, "SdbRegisterDatabase",
  1150. "Failed to set value \"%s\" to 0x%lx Error 0x%lx\n",
  1151. g_szDatabaseType, dwDatabaseType, lResult));
  1152. goto HandleError;
  1153. }
  1154. if (pDbInfo->pszDescription != NULL) {
  1155. lResult = RegSetValueEx(hKey,
  1156. g_szDatabaseDescription,
  1157. 0,
  1158. REG_SZ,
  1159. (PBYTE)pDbInfo->pszDescription,
  1160. (DWORD)(_tcslen(pDbInfo->pszDescription) + 1) * sizeof(*pDbInfo->pszDescription));
  1161. if (lResult != ERROR_SUCCESS) {
  1162. DBGPRINT((sdlError, "SdbRegisterDatabase",
  1163. "Failed to set value \"%s\" to 0x%lx Error 0x%lx\n",
  1164. g_szDatabaseDescription, pDbInfo->pszDescription, lResult));
  1165. goto HandleError;
  1166. }
  1167. }
  1168. bReturn = TRUE;
  1169. HandleError:
  1170. if (hKeyInstalledSDB != NULL) {
  1171. RegCloseKey(hKeyInstalledSDB);
  1172. }
  1173. if (hKey != NULL) {
  1174. RegCloseKey(hKey);
  1175. }
  1176. if (pDbInfo != NULL) {
  1177. SdbFreeDatabaseInformation(pDbInfo);
  1178. }
  1179. if (bFreeFullPath && pszFullPath != NULL) {
  1180. SdbFree(pszFullPath);
  1181. }
  1182. return bReturn;
  1183. }
  1184. DWORD
  1185. SDBAPI
  1186. SdbResolveDatabase(
  1187. IN HSDB hSDB,
  1188. IN GUID* pguidDB, // pointer to the database guid to resolve
  1189. OUT LPDWORD lpdwDatabaseType, // optional pointer to the database type
  1190. OUT LPTSTR pszDatabasePath, // optional pointer to the database path
  1191. IN DWORD dwBufferSize // size of the buffer pszDatabasePath in tchars
  1192. )
  1193. {
  1194. TCHAR szDatabasePath[MAX_PATH];
  1195. TCHAR szFullKey[512];
  1196. LONG lResult;
  1197. HKEY hKey = NULL;
  1198. DWORD dwDataType;
  1199. DWORD dwDataSize;
  1200. DWORD dwLength = 0;
  1201. //
  1202. // convert guid to string
  1203. //
  1204. if (!SdbGetDatabaseRegPath(pguidDB, szFullKey, CHARCOUNT(szFullKey))) {
  1205. DBGPRINT((sdlError, "SdbResolveDatabase", "Failed to retrieve database key path\n"));
  1206. goto HandleError;
  1207. }
  1208. //
  1209. // open the key
  1210. //
  1211. lResult = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1212. szFullKey,
  1213. 0,
  1214. KEY_READ,
  1215. &hKey);
  1216. if (lResult != ERROR_SUCCESS) {
  1217. DBGPRINT((sdlError, "SdbResolveDatabase",
  1218. "Failed to open key \"%s\" Error 0x%lx\n", szFullKey, lResult));
  1219. goto HandleError; // 0 means error
  1220. }
  1221. dwDataSize = sizeof(szDatabasePath);
  1222. lResult = RegQueryValueEx(hKey,
  1223. g_szDatabasePath,
  1224. NULL,
  1225. &dwDataType,
  1226. (LPBYTE)szDatabasePath,
  1227. &dwDataSize);
  1228. if (lResult != ERROR_SUCCESS) {
  1229. DBGPRINT((sdlError, "SdbResolveDatabase",
  1230. "Failed to query value \"%s\" Error 0x%lx\n", g_szDatabasePath, lResult));
  1231. goto HandleError; // 0 means error
  1232. }
  1233. switch(dwDataType) {
  1234. case REG_SZ:
  1235. // see if we have enough room to copy the string
  1236. //
  1237. if (dwBufferSize * sizeof(TCHAR) < dwDataSize) {
  1238. DBGPRINT((sdlWarning, "SdbResolveDatabase",
  1239. "Insufficient buffer for the database path Required 0x%lx Have 0x%lx\n",
  1240. dwDataSize, dwBufferSize * sizeof(TCHAR)));
  1241. goto HandleError;
  1242. }
  1243. RtlMoveMemory(pszDatabasePath, szDatabasePath, dwDataSize);
  1244. dwLength = dwDataSize / sizeof(TCHAR);
  1245. break;
  1246. case REG_EXPAND_SZ:
  1247. // we have to expand the strings
  1248. dwLength = ExpandEnvironmentStrings(szDatabasePath, pszDatabasePath, dwBufferSize);
  1249. if (dwLength == 0 || dwLength > dwBufferSize) {
  1250. DBGPRINT((sdlWarning, "SdbResolveDatabase",
  1251. "Failed to expand output path\n"));
  1252. dwLength = 0;
  1253. goto HandleError;
  1254. }
  1255. break;
  1256. default:
  1257. // can't do it -- fail
  1258. DBGPRINT((sdlError, "SdbResolveDatabase", "Wrong key type 0x%lx\n", dwDataType));
  1259. goto HandleError;
  1260. break;
  1261. }
  1262. if (lpdwDatabaseType != NULL) {
  1263. dwDataSize = sizeof(*lpdwDatabaseType);
  1264. lResult = RegQueryValueEx(hKey,
  1265. g_szDatabaseType,
  1266. NULL,
  1267. &dwDataType,
  1268. (LPBYTE)lpdwDatabaseType,
  1269. &dwDataSize);
  1270. if (lResult == ERROR_SUCCESS) {
  1271. if (dwDataType != REG_DWORD) {
  1272. // bummer, get out -- wrong type
  1273. DBGPRINT((sdlError, "SdbResolveDatabase",
  1274. "Wrong database type - value type 0x%lx\n", dwDataType));
  1275. dwLength = 0;
  1276. goto HandleError;
  1277. }
  1278. } else {
  1279. *lpdwDatabaseType = 0;
  1280. }
  1281. }
  1282. HandleError:
  1283. if (hKey != NULL) {
  1284. RegCloseKey(hKey);
  1285. }
  1286. return dwLength;
  1287. UNREFERENCED_PARAMETER(hSDB);
  1288. }
  1289. DWORD
  1290. SdbpGetProcessorArchitecture(
  1291. IN USHORT uExeType // executable's image type
  1292. )
  1293. {
  1294. SYSTEM_INFO SysInfo;
  1295. SysInfo.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_UNKNOWN;
  1296. GetSystemInfo(&SysInfo);
  1297. if (SysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64 ||
  1298. SysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 ||
  1299. SysInfo.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_ALPHA64) {
  1300. if (uExeType == IMAGE_FILE_MACHINE_I386) {
  1301. return PROCESSOR_ARCHITECTURE_IA32_ON_WIN64;
  1302. }
  1303. }
  1304. return (DWORD)SysInfo.wProcessorArchitecture;
  1305. }
  1306. BOOL
  1307. SdbpIsOs(
  1308. DWORD dwOSSKU
  1309. )
  1310. {
  1311. HKEY hkey = NULL;
  1312. DWORD type, cbSize, dwInstalled = 0;
  1313. LONG lRes;
  1314. LPTSTR pszKeyPath;
  1315. BOOL bRet = FALSE;
  1316. if (dwOSSKU == OS_SKU_TAB) {
  1317. pszKeyPath = TABLETPC_KEY_PATH;
  1318. } else if (dwOSSKU == OS_SKU_MED) {
  1319. pszKeyPath = EHOME_KEY_PATH;
  1320. } else {
  1321. DBGPRINT((sdlWarning,
  1322. "SdbpIsOs",
  1323. "Specified unknown OS type 0x%lx",
  1324. dwOSSKU));
  1325. return FALSE;
  1326. }
  1327. lRes = RegOpenKey(HKEY_LOCAL_MACHINE, pszKeyPath, &hkey);
  1328. if (lRes != ERROR_SUCCESS) {
  1329. goto cleanup;
  1330. }
  1331. cbSize = sizeof(DWORD);
  1332. lRes = RegQueryValueEx(hkey, IS_OS_INSTALL_VALUE, NULL, &type, (LPBYTE)&dwInstalled, &cbSize);
  1333. if (lRes != ERROR_SUCCESS || type != REG_DWORD) {
  1334. goto cleanup;
  1335. }
  1336. if (dwInstalled) {
  1337. bRet = TRUE;
  1338. }
  1339. DBGPRINT((sdlInfo|sdlLogShimViewer,
  1340. "SdbpIsOs",
  1341. "%s %s installed",
  1342. 0,
  1343. (dwOSSKU == OS_SKU_TAB ? TEXT("TabletPC") : TEXT("eHome")),
  1344. (bRet ? TEXT("is") : TEXT("is not"))));
  1345. cleanup:
  1346. RegCloseKey(hkey);
  1347. return bRet;
  1348. }
  1349. VOID
  1350. SdbpGetOSSKU(
  1351. LPDWORD lpdwSKU,
  1352. LPDWORD lpdwSP
  1353. )
  1354. {
  1355. OSVERSIONINFOEXA osv;
  1356. WORD wSuiteMask;
  1357. ZeroMemory(&osv, sizeof(OSVERSIONINFOEXA));
  1358. osv.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEXA);
  1359. GetVersionExA((LPOSVERSIONINFOA)&osv);
  1360. *lpdwSP = 1 << osv.wServicePackMajor;
  1361. wSuiteMask = osv.wSuiteMask;
  1362. if (osv.wProductType == VER_NT_WORKSTATION) {
  1363. if (wSuiteMask & VER_SUITE_PERSONAL) {
  1364. *lpdwSKU = OS_SKU_PER;
  1365. } else {
  1366. #if (_WIN32_WINNT >= 0x0501)
  1367. if (SdbpIsOs(OS_SKU_TAB)) {
  1368. *lpdwSKU = OS_SKU_TAB;
  1369. } else if (SdbpIsOs(OS_SKU_MED)) {
  1370. *lpdwSKU = OS_SKU_MED;
  1371. } else {
  1372. *lpdwSKU = OS_SKU_PRO;
  1373. }
  1374. #else
  1375. *lpdwSKU = OS_SKU_PRO;
  1376. #endif
  1377. }
  1378. return;
  1379. }
  1380. if (wSuiteMask & VER_SUITE_DATACENTER) {
  1381. *lpdwSKU = OS_SKU_DTC;
  1382. return;
  1383. }
  1384. if (wSuiteMask & VER_SUITE_ENTERPRISE) {
  1385. *lpdwSKU = OS_SKU_ADS;
  1386. return;
  1387. }
  1388. if (wSuiteMask & VER_SUITE_BLADE) {
  1389. *lpdwSKU = OS_SKU_BLA;
  1390. return;
  1391. }
  1392. if (wSuiteMask & VER_SUITE_SMALLBUSINESS) {
  1393. *lpdwSKU = OS_SKU_SBS;
  1394. return;
  1395. }
  1396. *lpdwSKU = OS_SKU_SRV;
  1397. }