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.

421 lines
8.3 KiB

  1. /*++
  2. STRINGS.CXX
  3. Copyright (C) 1999 Microsoft Corporation, all rights reserved.
  4. DESCRIPTION: MultiString class
  5. Created, Dec 29, 1999 by DavidCHR.
  6. CONTENTS: CMULTISTRING
  7. WriteToRegistry
  8. ReadFromRegistry
  9. RemoveString
  10. AddString
  11. ~CMULTISTRING
  12. --*/
  13. #include "everything.hxx"
  14. /*++**************************************************************
  15. NAME: CMULTISTRING
  16. constructor for the class.
  17. **************************************************************--*/
  18. CMULTISTRING::
  19. CMULTISTRING( VOID ) {
  20. this->cEntries = 0;
  21. this->pEntries = NULL;
  22. this->TotalStringCount = 0;
  23. }
  24. /*++**************************************************************
  25. NAME: ~CMULTISTRING
  26. destructor for the class. Frees any strings still around.
  27. **************************************************************--*/
  28. CMULTISTRING::
  29. ~CMULTISTRING( VOID ) {
  30. ULONG i;
  31. if ( this->cEntries &&
  32. this->pEntries ) {
  33. for ( i = 0 ;
  34. i < this->cEntries ;
  35. i ++ ) {
  36. if ( this->pEntries[ i ] ) {
  37. free( this->pEntries[ i ] );
  38. }
  39. }
  40. free( this->pEntries );
  41. }
  42. }
  43. /*++**************************************************************
  44. NAME: AddString
  45. adds a string to the end of string table
  46. MODIFIES: this->pEntries, this->cEntries
  47. TAKES: String -- string to add (duplicated)
  48. RETURNS: TRUE when the function succeeds.
  49. FALSE otherwise.
  50. LOGGING: printf on failure
  51. CREATED: Dec 29, 1999
  52. LOCKING: none
  53. CALLED BY: anyone
  54. FREE WITH: ~CMULTISTRING
  55. **************************************************************--*/
  56. BOOL CMULTISTRING::
  57. AddString( IN LPWSTR String ) {
  58. LPWSTR *tempString;
  59. tempString = (LPWSTR *) realloc( this->pEntries,
  60. ( this->cEntries + 1 ) *
  61. sizeof( LPWSTR ) );
  62. if ( tempString ) {
  63. this->pEntries = tempString;
  64. tempString[ this->cEntries ] = _wcsdup( String );
  65. if ( tempString[ this->cEntries ] ) {
  66. this->cEntries ++;
  67. this->TotalStringCount += wcslen( String );
  68. return TRUE;
  69. } else {
  70. printf( "Cannot add string %ld (%ws). Not enough memory.\n",
  71. this->cEntries,
  72. String );
  73. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  74. }
  75. // don't free the string.
  76. }
  77. return FALSE;
  78. }
  79. /*++**************************************************************
  80. NAME: RemoveString
  81. removes a string from the list
  82. MODIFIES: this->pEntries, this->cEntries
  83. TAKES: String -- string to remove (case-insensitive)
  84. RETURNS: TRUE when the function succeeds.
  85. FALSE otherwise.
  86. LOGGING: printf if the string doesn't exist
  87. CREATED: Dec 29, 1999
  88. LOCKING: none
  89. CALLED BY: anyone
  90. FREE WITH: n/a -- no resources are allocated
  91. **************************************************************--*/
  92. BOOL CMULTISTRING::
  93. RemoveString( IN LPWSTR String ) {
  94. ULONG i, DeleteCount = 0;
  95. BOOL ret = TRUE;
  96. // first, go through and free the matches
  97. for ( i = 0 ;
  98. i < this->cEntries ;
  99. i ++ ) {
  100. if ( _wcsicmp( String,
  101. this->pEntries[ i ] ) == 0 ) {
  102. // match. Free it.
  103. free( this->pEntries[ i ] );
  104. this->pEntries[ i ] = NULL;
  105. DeleteCount++;
  106. } else if ( DeleteCount > 0 ) {
  107. /* If we've deleted stuff already, and we're not deleting
  108. this one, then move this entry earlier in the array. */
  109. this->pEntries[ i - DeleteCount ] = this->pEntries[ i ];
  110. #if DBG
  111. /* For the sake of debugging, set this to a known
  112. bad value. */
  113. #ifdef _WIN64 // to avoid ia64 compile-time error, give it a qword for a pointer
  114. this->pEntries[ i ] = (LPWSTR) 0xdeadbeefdeadbeef;
  115. #else
  116. this->pEntries[ i ] = (LPWSTR) ULongToPtr( 0xdeadbeef );
  117. #endif // _WIN64
  118. #endif // DBG
  119. }
  120. }
  121. if ( DeleteCount ) {
  122. this->cEntries -= DeleteCount;
  123. this->TotalStringCount -= DeleteCount * wcslen( String );
  124. /* We could realloc the array down to the correct cEntries now,
  125. but there's no pressing need. */
  126. } else {
  127. printf( "No match for %ws.\n",
  128. String );
  129. ret = FALSE;
  130. }
  131. return ret;
  132. }
  133. /*++**************************************************************
  134. NAME: ReadFromRegistry
  135. reads a string vector from a REG_MULTI_SZ in the registry
  136. MODIFIES: this, indirectly
  137. TAKES: hKey -- handle to open parent key
  138. ValueName -- value to read
  139. RETURNS: TRUE when the function succeeds.
  140. FALSE otherwise.
  141. LOGGING: printf on failure
  142. CREATED: Dec 29, 1999
  143. LOCKING: none
  144. CALLED BY: anyone
  145. FREE WITH: n/a -- no resources are allocated
  146. **************************************************************--*/
  147. BOOL CMULTISTRING::
  148. ReadFromRegistry( IN HKEY hKey,
  149. IN LPWSTR ValueName ) {
  150. ULONG RegistrySize = 0;
  151. ULONG cEntries = 0;
  152. LPWSTR RegistryStrings;
  153. LPWSTR *StringTable = NULL;
  154. LPWSTR *pTempTable, Cursor;
  155. DWORD WinError;
  156. DWORD Type;
  157. BOOL ret = FALSE;
  158. WinError = RegQueryValueEx( hKey,
  159. ValueName,
  160. NULL,
  161. &Type,
  162. NULL,
  163. &RegistrySize );
  164. if (WinError == ERROR_SUCCESS) {
  165. RegistryStrings = (LPWSTR) malloc( RegistrySize );
  166. if ( RegistryStrings ) {
  167. WinError = RegQueryValueEx( hKey,
  168. ValueName,
  169. NULL,
  170. &Type,
  171. (PUCHAR) RegistryStrings,
  172. &RegistrySize );
  173. if (WinError == ERROR_SUCCESS) {
  174. ret = TRUE;
  175. if ( RegistrySize > 2 * sizeof( WCHAR ) ) { /* 2 == two nulls
  176. which would indicate
  177. that the value is
  178. empty. */
  179. /* Now, allocate a string vector, counting the strings
  180. as we go. */
  181. for ( Cursor = RegistryStrings ;
  182. *Cursor != L'\0' ;
  183. Cursor = wcschr( Cursor, '\0' ) +1 ) {
  184. if ( !this->AddString( Cursor ) ) {
  185. ret = FALSE;
  186. break;
  187. }
  188. }
  189. } // else the value was empty -- nothing to do.
  190. } else {
  191. printf("Failed to query value %ws: 0x%x\n",
  192. ValueName,
  193. WinError );
  194. }
  195. free( RegistryStrings );
  196. } else {
  197. printf( "Failed to allocate %hs buffer (0x%x)\n",
  198. ValueName,
  199. RegistrySize );
  200. }
  201. } else if ( WinError == ERROR_FILE_NOT_FOUND ) {
  202. /* The key doesn't exist-- no mappings. */
  203. // WinError = ERROR_SUCCESS;
  204. ret = TRUE;
  205. } else {
  206. /* an actual error. */
  207. printf( "Failed to query %ws: 0x%x\n",
  208. ValueName,
  209. WinError );
  210. }
  211. return ret;
  212. }
  213. /*++**************************************************************
  214. NAME: WriteToRegistry
  215. dumps the string vector to a REG_MULTI_SZ in the registry
  216. MODIFIES: the registry only
  217. TAKES: hKey -- handle to open parent key
  218. ValueName -- value to write
  219. RETURNS: TRUE when the function succeeds.
  220. FALSE otherwise.
  221. LOGGING: printf on failure
  222. CREATED: Dec 29, 1999
  223. LOCKING: none
  224. CALLED BY: anyone
  225. FREE WITH: n/a -- no resources are allocated
  226. **************************************************************--*/
  227. BOOL CMULTISTRING::
  228. WriteToRegistry( IN HKEY hKey,
  229. IN LPWSTR ValueName ) {
  230. LPWSTR StringVector;
  231. ULONG StringIndex, EntryIndex, Length, VectorLength;
  232. DWORD dwErr;
  233. BOOL ret = FALSE;
  234. VectorLength = ( this->TotalStringCount + // string characters
  235. this->cEntries + // null characters
  236. 2 // trailing nulls
  237. ) * sizeof( WCHAR );
  238. StringVector = (LPWSTR) malloc( VectorLength );
  239. if ( !StringVector ) {
  240. printf( "Failed to allocate string blob to write %ws.\n",
  241. ValueName );
  242. } else {
  243. for ( StringIndex = EntryIndex = 0 ;
  244. EntryIndex < this->cEntries ;
  245. EntryIndex++ ) {
  246. Length = wcslen( this->pEntries[ EntryIndex ] ) +1; /* include the
  247. null */
  248. memcpy( StringVector + StringIndex, // to
  249. this->pEntries[ EntryIndex ], // from
  250. Length * sizeof( WCHAR ) ); // byte count
  251. StringIndex += Length;
  252. }
  253. StringVector[ StringIndex ] = L'\0';
  254. StringVector[ StringIndex+1 ] = L'\0';
  255. dwErr = RegSetValueExW( hKey,
  256. ValueName,
  257. 0, // mbz
  258. REG_MULTI_SZ,
  259. (PBYTE) StringVector,
  260. VectorLength );
  261. free( StringVector );
  262. if ( dwErr != ERROR_SUCCESS ) {
  263. printf( "Failed to write %ws value to registry: 0x%x.\n",
  264. ValueName,
  265. dwErr );
  266. } else {
  267. ret = TRUE;
  268. }
  269. }
  270. return ret;
  271. }