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.

207 lines
4.7 KiB

  1. #include "cstore.hxx"
  2. HRESULT
  3. GetAppmgmtIniFilePath(
  4. PSID pSid,
  5. LPWSTR* ppwszPath
  6. )
  7. {
  8. UNICODE_STRING SidString;
  9. PTOKEN_USER pTokenUser;
  10. WCHAR wszPath[MAX_PATH];
  11. WCHAR * pwszSystemDir;
  12. DWORD AllocLength;
  13. DWORD Length;
  14. DWORD Size;
  15. DWORD Status;
  16. BOOL bStatus;
  17. Status = ERROR_SUCCESS;
  18. *ppwszPath = 0;
  19. pwszSystemDir = wszPath;
  20. AllocLength = sizeof(wszPath) / sizeof(WCHAR);
  21. for (;;)
  22. {
  23. Length = GetSystemDirectory(
  24. pwszSystemDir,
  25. AllocLength );
  26. if ( 0 == Length )
  27. return HRESULT_FROM_WIN32(GetLastError());
  28. if ( Length >= AllocLength )
  29. {
  30. AllocLength = Length + 1;
  31. //
  32. // No check for failure of alloca since it throws an
  33. // exception on failure
  34. //
  35. pwszSystemDir = (WCHAR *) alloca( AllocLength * sizeof(WCHAR) );
  36. continue;
  37. }
  38. break;
  39. }
  40. if ( pSid )
  41. {
  42. if ( ERROR_SUCCESS == Status )
  43. {
  44. Status = RtlConvertSidToUnicodeString(
  45. &SidString,
  46. pSid,
  47. TRUE );
  48. }
  49. if ( Status != ERROR_SUCCESS )
  50. return HRESULT_FROM_WIN32(Status);
  51. }
  52. else
  53. {
  54. RtlInitUnicodeString( &SidString, L"MACHINE" );
  55. }
  56. // System dir + \appmgmt\ + Sid \ + inifilename \ + null
  57. *ppwszPath = new WCHAR[Length + 11 + (SidString.Length / 2) +
  58. (sizeof(APPMGMT_INI_FILENAME) / sizeof(WCHAR))];
  59. if ( *ppwszPath )
  60. {
  61. lstrcpy( *ppwszPath, pwszSystemDir );
  62. if ( pwszSystemDir[lstrlen(pwszSystemDir)-1] != L'\\' )
  63. lstrcat( *ppwszPath, L"\\" );
  64. lstrcat( *ppwszPath, L"appmgmt\\" );
  65. lstrcat( *ppwszPath, SidString.Buffer );
  66. lstrcat( *ppwszPath, APPMGMT_INI_FILENAME );
  67. }
  68. else
  69. {
  70. Status = ERROR_OUTOFMEMORY;
  71. }
  72. if ( pSid )
  73. RtlFreeUnicodeString( &SidString );
  74. return HRESULT_FROM_WIN32(Status);
  75. }
  76. HRESULT ReadClassStorePath(PSID pSid, LPWSTR* ppwszClassStorePath)
  77. {
  78. HRESULT hr;
  79. LPWSTR wszIniFilePath;
  80. hr = GetAppmgmtIniFilePath(
  81. pSid,
  82. &wszIniFilePath);
  83. if (FAILED(hr))
  84. {
  85. return hr;
  86. }
  87. DWORD nBufferSize;
  88. DWORD nCharsReceived;
  89. LPWSTR wszResult;
  90. nBufferSize = DEFAULT_CSPATH_LENGTH;
  91. wszResult = NULL;
  92. //
  93. // The GetPrivateProfileString function is so horribly designed
  94. // that we have to write this disgusting code below to deal with it
  95. //
  96. for (DWORD dwRetry = 0; dwRetry < 7; dwRetry++)
  97. {
  98. WCHAR DefaultBuffer = L'\0';
  99. wszResult = new WCHAR [nBufferSize];
  100. if (!wszResult)
  101. {
  102. hr = E_OUTOFMEMORY;
  103. break;
  104. }
  105. //
  106. // It turns out that this api has other issues as well -- if the file
  107. // doesn't exist it doesn't even return an error that would
  108. // make sense (like 0) -- instead, I've seen it return 8!
  109. // To get around this interesting behavior, I'll set the first
  110. // character of the string to L'\0' before calling the api -- this means that
  111. // subsequent code will treat the failure as if we read a
  112. // zero length class store path from the file, which is the
  113. // desired behavior.
  114. //
  115. *wszResult = L'\0';
  116. nCharsReceived = GetPrivateProfileString(
  117. APPMGMT_INI_CSTORE_SECTIONNAME,
  118. APPMGMT_INI_CSPATH_KEYNAME,
  119. &DefaultBuffer,
  120. wszResult,
  121. nBufferSize,
  122. wszIniFilePath);
  123. //
  124. // If nothing is written, then there's no point in going forward
  125. // since this api returns the number of characters we need to write
  126. //
  127. if (!nCharsReceived)
  128. {
  129. hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
  130. break;
  131. }
  132. if (nCharsReceived != (nBufferSize - 1))
  133. {
  134. break;
  135. }
  136. //
  137. // Double the size of the allocation
  138. //
  139. nBufferSize *= 2;
  140. //
  141. // Free the previous allocation
  142. //
  143. delete [] wszResult;
  144. wszResult = NULL;
  145. }
  146. if (wszResult && nCharsReceived)
  147. {
  148. LPWSTR wszAllocatedCSPathForCaller;
  149. *ppwszClassStorePath = new WCHAR[nCharsReceived + 1];
  150. if (*ppwszClassStorePath)
  151. {
  152. wcscpy(*ppwszClassStorePath, wszResult);
  153. }
  154. else
  155. {
  156. hr = E_OUTOFMEMORY;
  157. }
  158. }
  159. delete [] wszResult;
  160. delete [] wszIniFilePath;
  161. return hr;
  162. }