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.

445 lines
13 KiB

  1. //-----------------------------------------------------------------------//
  2. //
  3. // File: add.cpp
  4. // Created: March 1997
  5. // By: Martin Holladay (a-martih)
  6. // Purpose: Registry Add (Write) Support for REG.CPP
  7. // Modification History:
  8. // March 1997 (a-martih):
  9. // Copied from Query.cpp and modificd.
  10. // October 1997 (martinho)
  11. // Added additional termination character for MULTI_SZ strings.
  12. // Added \0 delimiter between MULTI_SZ strings items
  13. // April 1999 Zeyong Xu: re-design, revision -> version 2.0
  14. //------------------------------------------------------------------------//
  15. #include "stdafx.h"
  16. #include "reg.h"
  17. //-----------------------------------------------------------------------//
  18. //
  19. // AddRegistry()
  20. //
  21. //-----------------------------------------------------------------------//
  22. LONG AddRegistry(PAPPVARS pAppVars, UINT argc, TCHAR *argv[])
  23. {
  24. LONG nResult;
  25. HKEY hKey;
  26. DWORD dwDisposition;
  27. BYTE* byteData;
  28. //
  29. // Parse the cmd-line
  30. //
  31. nResult = ParseAddCmdLine(pAppVars, argc, argv);
  32. if(nResult != ERROR_SUCCESS)
  33. {
  34. return nResult;
  35. }
  36. //
  37. // Connect to the Remote Machine - if applicable
  38. //
  39. nResult = RegConnectMachine(pAppVars);
  40. if (nResult != ERROR_SUCCESS)
  41. {
  42. return nResult;
  43. }
  44. //
  45. // Create/Open the registry key
  46. //
  47. nResult = RegCreateKeyEx(pAppVars->hRootKey,
  48. pAppVars->szSubKey,
  49. 0,
  50. NULL,
  51. REG_OPTION_NON_VOLATILE,
  52. KEY_READ | KEY_WRITE,
  53. NULL,
  54. &hKey,
  55. &dwDisposition);
  56. if( nResult == ERROR_SUCCESS &&
  57. pAppVars->szValueName )
  58. {
  59. // check value if existed
  60. DWORD dwType;
  61. DWORD dwLen = 1;
  62. nResult = RegQueryValueEx(hKey,
  63. pAppVars->szValueName,
  64. NULL,
  65. &dwType,
  66. NULL,
  67. &dwLen);
  68. if(nResult == ERROR_SUCCESS)
  69. {
  70. // if exist
  71. if(!Prompt(_T("Value %s exists, overwrite(Y/N)? "),
  72. pAppVars->szValueName,
  73. pAppVars->bForce) )
  74. {
  75. RegCloseKey(hKey);
  76. return nResult;
  77. }
  78. }
  79. nResult = ERROR_SUCCESS;
  80. switch(pAppVars->dwRegDataType)
  81. {
  82. case REG_DWORD:
  83. case REG_DWORD_BIG_ENDIAN:
  84. // case REG_DWORD_LITTLE_ENDIAN:
  85. //
  86. // auto convert szValue (hex, octal, decimal format) to dwData
  87. //
  88. {
  89. TCHAR* szStop = NULL;
  90. DWORD dwData = _tcstoul(pAppVars->szValue, &szStop, 0);
  91. if(_tcslen(szStop) > 0) // invalid data format
  92. nResult = REG_STATUS_INVALIDPARAMS;
  93. else
  94. nResult = RegSetValueEx(hKey,
  95. pAppVars->szValueName,
  96. 0,
  97. pAppVars->dwRegDataType,
  98. (BYTE*) &dwData,
  99. sizeof(DWORD));
  100. }
  101. break;
  102. case REG_BINARY:
  103. {
  104. TCHAR buff[3];
  105. LONG onebyte;
  106. LONG count = 0;
  107. TCHAR* szStart;
  108. TCHAR* szStop;
  109. //
  110. // Convert szValue (hex data string) to binary
  111. //
  112. dwLen = _tcslen(pAppVars->szValue);
  113. byteData = (BYTE*) calloc(dwLen/2 + dwLen%2,
  114. sizeof(BYTE));
  115. if (!byteData) {
  116. nResult = ERROR_NOT_ENOUGH_MEMORY;
  117. goto Cleanup;
  118. }
  119. buff[2] = _T('\0');
  120. count = 0;
  121. szStart = pAppVars->szValue;
  122. while(_tcslen(szStart) > 0)
  123. {
  124. buff[0] = *szStart;
  125. szStart++;
  126. if(_tcslen(szStart) > 0)
  127. {
  128. buff[1] = *szStart;
  129. szStart++;
  130. }
  131. else
  132. {
  133. buff[1] = _T('0'); // if half byte, append a '0'
  134. }
  135. // hex format
  136. onebyte = _tcstol(buff, &szStop, 16);
  137. if(_tcslen(szStop) > 0) // invalid data format
  138. {
  139. nResult = REG_STATUS_INVALIDPARAMS;
  140. break;
  141. }
  142. else
  143. {
  144. byteData[count] = (BYTE)(onebyte);
  145. }
  146. count++;
  147. }
  148. if(nResult == ERROR_SUCCESS)
  149. {
  150. nResult = RegSetValueEx(hKey,
  151. pAppVars->szValueName,
  152. 0,
  153. pAppVars->dwRegDataType,
  154. byteData,
  155. count);
  156. }
  157. if(byteData)
  158. free(byteData);
  159. }
  160. break;
  161. case REG_SZ:
  162. case REG_EXPAND_SZ:
  163. case REG_NONE:
  164. dwLen = (_tcslen(pAppVars->szValue) + 1) * sizeof(TCHAR);
  165. nResult = RegSetValueEx(hKey,
  166. pAppVars->szValueName,
  167. 0,
  168. pAppVars->dwRegDataType,
  169. (BYTE*) pAppVars->szValue,
  170. dwLen);
  171. break;
  172. case REG_MULTI_SZ:
  173. {
  174. BOOL bErrorString = FALSE;
  175. DWORD dwLengthOfSeparator = _tcslen(pAppVars->szSeparator);
  176. BOOL bTrailing = FALSE;
  177. TCHAR* szData;
  178. TCHAR* pStart;
  179. TCHAR* pEnd;
  180. TCHAR* pString;
  181. //
  182. // Replace separator("\0") with '\0' for MULTI_SZ,
  183. // "\0" uses to separate string by default,
  184. // if two separators("\0\0"), error
  185. //
  186. dwLen = _tcslen(pAppVars->szValue);
  187. // calloc() initializes all char to 0
  188. szData = (TCHAR*) calloc(dwLen + 2, sizeof(TCHAR));
  189. pStart = pAppVars->szValue;
  190. pString = szData;
  191. if (!szData) {
  192. nResult = ERROR_NOT_ENOUGH_MEMORY;
  193. goto Cleanup;
  194. }
  195. while(_tcslen(pStart) > 0)
  196. {
  197. pEnd = _tcsstr(pStart, pAppVars->szSeparator);
  198. if(pEnd)
  199. {
  200. /*
  201. **** MODIFIED BY V-SMGUM ****
  202. //two separators("\0\0") inside string
  203. if( pEnd == pStart ||
  204. //one separator("\0") in end of string
  205. _tcslen(pEnd) == dwLengthOfSeparator)
  206. {
  207. bErrorString = TRUE;
  208. break;
  209. }
  210. *pEnd = 0;
  211. */
  212. //
  213. // MODIFIED BY V-SMGUM
  214. // THIS IS TO REMOVE THE TRAILING SEPERATOR EVEN IF IT IS SPECIFIED
  215. //
  216. // specifying two seperators in the data is error
  217. bTrailing = FALSE;
  218. if ( pEnd == pStart )
  219. {
  220. bErrorString = TRUE;
  221. break;
  222. }
  223. else if ( _tcslen( pEnd ) == dwLengthOfSeparator )
  224. {
  225. // set the flag
  226. bTrailing = TRUE;
  227. }
  228. *pEnd = 0;
  229. }
  230. // do the concat only if start is having valid buffer
  231. _tcscat(pString, pStart);
  232. pString += _tcslen(pString) + 1;
  233. if( pEnd && bTrailing == FALSE )
  234. pStart = pEnd + dwLengthOfSeparator;
  235. else
  236. break;
  237. }
  238. // empty
  239. if(_tcsicmp(pAppVars->szValue, pAppVars->szSeparator) == 0)
  240. {
  241. pString = szData + 2;
  242. bErrorString = FALSE;
  243. }
  244. else
  245. pString += 1; // double null terminated string
  246. if(bErrorString)
  247. {
  248. nResult = REG_STATUS_INVALIDPARAMS;
  249. }
  250. else
  251. {
  252. DWORD dwByteToWrite = (DWORD)((pString - szData) * sizeof(TCHAR));
  253. nResult = RegSetValueEx(hKey,
  254. pAppVars->szValueName,
  255. 0,
  256. pAppVars->dwRegDataType,
  257. (BYTE*) szData,
  258. dwByteToWrite);
  259. }
  260. if(szData)
  261. free(szData);
  262. }
  263. break;
  264. default:
  265. nResult = REG_STATUS_INVALIDPARAMS;
  266. break;
  267. }
  268. RegCloseKey(hKey);
  269. }
  270. Cleanup:
  271. return nResult;
  272. }
  273. //------------------------------------------------------------------------//
  274. //
  275. // ParseAddCmdLine()
  276. //
  277. //------------------------------------------------------------------------//
  278. REG_STATUS ParseAddCmdLine(PAPPVARS pAppVars, UINT argc, TCHAR *argv[])
  279. {
  280. REG_STATUS nResult = ERROR_SUCCESS;
  281. UINT i;
  282. BOOL bHasType = FALSE;
  283. if(argc < 3)
  284. {
  285. return REG_STATUS_TOFEWPARAMS;
  286. }
  287. // Machine Name and Registry key
  288. //
  289. nResult = BreakDownKeyString(argv[2], pAppVars);
  290. if(nResult != ERROR_SUCCESS)
  291. return nResult;
  292. // parsing
  293. for(i=3; i<argc; i++)
  294. {
  295. if(!_tcsicmp(argv[i], _T("/v")))
  296. {
  297. if(pAppVars->szValueName)
  298. return REG_STATUS_INVALIDPARAMS;
  299. i++;
  300. if(i<argc)
  301. {
  302. pAppVars->szValueName = (TCHAR*) calloc(_tcslen(argv[i]) + 1,
  303. sizeof(TCHAR));
  304. if (!pAppVars->szValueName) {
  305. return ERROR_NOT_ENOUGH_MEMORY;
  306. }
  307. _tcscpy(pAppVars->szValueName, argv[i]);
  308. }
  309. else
  310. return REG_STATUS_TOFEWPARAMS;
  311. }
  312. else if(!_tcsicmp(argv[i], _T("/ve")))
  313. {
  314. if(pAppVars->szValueName)
  315. return REG_STATUS_INVALIDPARAMS;
  316. pAppVars->szValueName = (TCHAR*) calloc(1, sizeof(TCHAR));
  317. if (!pAppVars->szValueName) {
  318. return ERROR_NOT_ENOUGH_MEMORY;
  319. }
  320. }
  321. else if(!_tcsicmp(argv[i], _T("/t")))
  322. {
  323. i++;
  324. if(i<argc)
  325. {
  326. pAppVars->dwRegDataType = IsRegDataType(argv[i]);
  327. if(pAppVars->dwRegDataType == (DWORD)-1)
  328. {
  329. return REG_STATUS_INVALIDPARAMS;
  330. }
  331. bHasType = TRUE;
  332. }
  333. else
  334. return REG_STATUS_TOFEWPARAMS;
  335. }
  336. else if(!_tcsicmp(argv[i], _T("/s")))
  337. {
  338. if(pAppVars->dwRegDataType != REG_MULTI_SZ)
  339. return REG_STATUS_INVALIDPARAMS;
  340. i++;
  341. if(i<argc)
  342. {
  343. if(_tcslen(argv[i]) == 1)
  344. {
  345. _tcscpy(pAppVars->szSeparator, argv[i]);
  346. }
  347. else
  348. return REG_STATUS_INVALIDPARAMS;
  349. }
  350. else
  351. return REG_STATUS_TOFEWPARAMS;
  352. }
  353. else if(!_tcsicmp(argv[i], _T("/d")))
  354. {
  355. if(pAppVars->szValue)
  356. return REG_STATUS_INVALIDPARAMS;
  357. i++;
  358. if(i<argc)
  359. {
  360. pAppVars->szValue = (TCHAR*) calloc(_tcslen(argv[i]) + 1,
  361. sizeof(TCHAR));
  362. if (!pAppVars->szValue) {
  363. return ERROR_NOT_ENOUGH_MEMORY;
  364. }
  365. _tcscpy(pAppVars->szValue, argv[i]);
  366. }
  367. else
  368. return REG_STATUS_TOFEWPARAMS;
  369. }
  370. else if(!_tcsicmp(argv[i], _T("/f")))
  371. {
  372. pAppVars->bForce = TRUE;
  373. }
  374. else
  375. return REG_STATUS_TOMANYPARAMS;
  376. }
  377. // if no value, set to empty value data
  378. if(pAppVars->szValueName && !pAppVars->szValue)
  379. {
  380. pAppVars->szValue = (TCHAR*) calloc(1, sizeof(TCHAR));
  381. if (!pAppVars->szValue) {
  382. return ERROR_NOT_ENOUGH_MEMORY;
  383. }
  384. *(pAppVars->szValue) = 0;
  385. }
  386. else if( !pAppVars->szValueName &&
  387. (bHasType || pAppVars->szValue) )
  388. {
  389. return REG_STATUS_INVALIDPARAMS;
  390. }
  391. return ERROR_SUCCESS;
  392. }