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
13 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996.
  5. //
  6. // File: actmisc.cxx
  7. //
  8. // Contents: Miscellaneous functions.
  9. //
  10. // Functions:
  11. //
  12. // History:
  13. //
  14. //--------------------------------------------------------------------------
  15. #include "act.hxx"
  16. //-------------------------------------------------------------------------
  17. //
  18. // GetSystemDir
  19. //
  20. // Returns the system directory path.
  21. //
  22. // ppwszSystemDir is allocated by this routine and should be freed by the
  23. // caller.
  24. //
  25. //-------------------------------------------------------------------------
  26. HRESULT
  27. GetSystemDir(
  28. OUT WCHAR ** ppwszSystemDir
  29. )
  30. {
  31. DWORD PathChars;
  32. WCHAR * pszSystemDir;
  33. *ppwszSystemDir = 0;
  34. PathChars = GetSystemDirectory( NULL, 0 );
  35. if ( ! PathChars )
  36. return HRESULT_FROM_WIN32( GetLastError() );
  37. // I don't trust these APIs to include the null.
  38. PathChars++;
  39. pszSystemDir = (WCHAR *) PrivMemAlloc( PathChars * sizeof(WCHAR) );
  40. if ( ! pszSystemDir )
  41. return E_OUTOFMEMORY;
  42. PathChars = GetSystemDirectoryW( pszSystemDir, PathChars );
  43. if ( ! PathChars )
  44. {
  45. PrivMemFree( pszSystemDir );
  46. return HRESULT_FROM_WIN32( GetLastError() );
  47. }
  48. #if 1 // #ifndef _CHICAGO_
  49. *ppwszSystemDir = pszSystemDir;
  50. return S_OK;
  51. #else
  52. *ppwszSystemDir = (WCHAR *) PrivMemAlloc( PathChars * sizeof(WCHAR) );
  53. PathChars = MultiByteToWideChar(
  54. CP_ACP,
  55. 0,
  56. pszSystemDir,
  57. -1,
  58. *ppwszSystemDir,
  59. PathChars );
  60. PrivMemFree( pszSystemDir );
  61. if ( ! PathChars )
  62. {
  63. PrivMemFree( *ppwszSystemDir );
  64. return HRESULT_FROM_WIN32( GetLastError() );
  65. }
  66. else
  67. {
  68. return S_OK;
  69. }
  70. #endif
  71. }
  72. HRESULT GetMachineName(
  73. WCHAR * pwszPath,
  74. WCHAR wszMachineName[MAX_COMPUTERNAME_LENGTH+1]
  75. #ifdef DFSACTIVATION
  76. ,BOOL bDoDfsConversion
  77. #endif
  78. )
  79. {
  80. WCHAR * pwszServerName;
  81. BYTE Buffer[sizeof(REMOTE_NAME_INFO)+MAX_PATH*sizeof(WCHAR)];
  82. DWORD BufferSize = sizeof(Buffer);
  83. WCHAR Drive[4];
  84. DWORD Status;
  85. //
  86. // Extract the server name from the file's path name.
  87. //
  88. if ( pwszPath[0] != L'\\' || pwszPath[1] != L'\\' )
  89. {
  90. lstrcpynW(Drive, pwszPath, 3);
  91. Drive[2] = L'\\';
  92. Drive[3] = NULL;
  93. // We must impersonate around the call to GetDriveType as well,
  94. // so that we have the same access to the mapped drive as the
  95. // calling client.
  96. if ( RpcImpersonateClient((RPC_BINDING_HANDLE)0) != ERROR_SUCCESS )
  97. return CO_E_SCM_RPC_FAILURE;
  98. if (GetDriveType(Drive) != DRIVE_REMOTE )
  99. {
  100. RpcRevertToSelf();
  101. return S_FALSE;
  102. }
  103. Status = ScmWNetGetUniversalName( pwszPath,
  104. UNIVERSAL_NAME_INFO_LEVEL,
  105. Buffer,
  106. &BufferSize );
  107. RpcRevertToSelf();
  108. if ( Status != NO_ERROR )
  109. {
  110. return CO_E_BAD_PATH;
  111. }
  112. pwszPath = ((UNIVERSAL_NAME_INFO *)Buffer)->lpUniversalName;
  113. if ( ! pwszPath || pwszPath[0] != L'\\' || pwszPath[1] != L'\\' )
  114. {
  115. // Must be a local path.
  116. return S_FALSE;
  117. }
  118. }
  119. #ifdef DFSACTIVATION
  120. WCHAR wszDfsPath[MAX_PATH];
  121. WCHAR * pwszDfsPath = wszDfsPath;
  122. if ( bDoDfsConversion && ghDfs )
  123. {
  124. DWORD DfsPathLen;
  125. DfsPathLen = sizeof(wszDfsPath);
  126. for (;;)
  127. {
  128. Status = DfsFsctl(
  129. ghDfs,
  130. FSCTL_DFS_GET_SERVER_NAME,
  131. (PVOID) &pwszPath[1],
  132. lstrlenW(&pwszPath[1]) * sizeof(WCHAR),
  133. (PVOID) pwszDfsPath,
  134. &DfsPathLen );
  135. if ( Status == STATUS_BUFFER_OVERFLOW )
  136. {
  137. Win4Assert( pwszDfsPath == wszDfsPath );
  138. pwszDfsPath = (WCHAR *) PrivMemAlloc( DfsPathLen );
  139. if ( ! pwszDfsPath )
  140. return E_OUTOFMEMORY;
  141. continue;
  142. }
  143. break;
  144. }
  145. if ( Status == STATUS_SUCCESS )
  146. pwszPath = pwszDfsPath;
  147. }
  148. #endif
  149. // Skip the "\\".
  150. LPWSTR pwszTemp = pwszPath + 2;
  151. pwszServerName = wszMachineName;
  152. while ( *pwszTemp != L'\\' )
  153. *pwszServerName++ = *pwszTemp++;
  154. *pwszServerName = 0;
  155. #ifdef DFSACTIVATION
  156. if ( pwszDfsPath != wszDfsPath )
  157. PrivMemFree( pwszDfsPath );
  158. #endif
  159. return S_OK;
  160. }
  161. HRESULT GetPathForServer(
  162. WCHAR * pwszPath,
  163. WCHAR wszPathForServer[MAX_PATH+1],
  164. WCHAR ** ppwszPathForServer )
  165. {
  166. BYTE Buffer[sizeof(REMOTE_NAME_INFO)+MAX_PATH*sizeof(WCHAR)];
  167. WCHAR Drive[4];
  168. DWORD BufferSize = sizeof(Buffer);
  169. DWORD PathLength;
  170. DWORD Status;
  171. UINT uiDriveType;
  172. *ppwszPathForServer = 0;
  173. if ( pwszPath &&
  174. (lstrlenW(pwszPath) >= 3) &&
  175. (pwszPath[1] == L':') && (pwszPath[2] == L'\\') )
  176. {
  177. lstrcpynW(Drive, pwszPath, 3);
  178. Drive[2] = L'\\';
  179. Drive[3] = NULL;
  180. // We must impersonate around the call to GetDriveType as well,
  181. // so that we have the same access to the mapped drive as the
  182. // calling client.
  183. if ( RpcImpersonateClient((RPC_BINDING_HANDLE)0) != ERROR_SUCCESS )
  184. return CO_E_SCM_RPC_FAILURE;
  185. uiDriveType = GetDriveType( Drive );
  186. RpcRevertToSelf();
  187. switch ( uiDriveType )
  188. {
  189. case 0 : // Drive type can not be determined
  190. case 1 : // The root directory does not exist
  191. case DRIVE_CDROM :
  192. case DRIVE_RAMDISK :
  193. case DRIVE_REMOVABLE :
  194. //
  195. // We can't convert these to file names that the server will be
  196. // able to access.
  197. //
  198. return CO_E_BAD_PATH;
  199. case DRIVE_FIXED :
  200. if ( 0 == gpMachineName )
  201. {
  202. return E_OUTOFMEMORY;
  203. }
  204. wszPathForServer[0] = wszPathForServer[1] = L'\\';
  205. lstrcpyW( &wszPathForServer[2], gpMachineName->Name() );
  206. PathLength = lstrlenW( wszPathForServer );
  207. wszPathForServer[PathLength] = L'\\';
  208. wszPathForServer[PathLength+1] = pwszPath[0];
  209. wszPathForServer[PathLength+2] = L'$';
  210. wszPathForServer[PathLength+3] = L'\\';
  211. lstrcpyW( &wszPathForServer[PathLength+4], &pwszPath[3] );
  212. *ppwszPathForServer = wszPathForServer;
  213. break;
  214. case DRIVE_REMOTE :
  215. if ( RpcImpersonateClient((RPC_BINDING_HANDLE)0) != ERROR_SUCCESS )
  216. return CO_E_SCM_RPC_FAILURE;
  217. Status = ScmWNetGetUniversalName( pwszPath,
  218. UNIVERSAL_NAME_INFO_LEVEL,
  219. Buffer,
  220. &BufferSize );
  221. RpcRevertToSelf();
  222. if ( Status != NO_ERROR )
  223. {
  224. return CO_E_BAD_PATH;
  225. }
  226. Win4Assert( ((UNIVERSAL_NAME_INFO *)Buffer)->lpUniversalName );
  227. lstrcpyW( wszPathForServer, ((UNIVERSAL_NAME_INFO *)Buffer)->lpUniversalName );
  228. *ppwszPathForServer = wszPathForServer;
  229. Win4Assert( wszPathForServer[0] == L'\\' &&
  230. wszPathForServer[1] == L'\\' );
  231. break;
  232. }
  233. }
  234. else
  235. {
  236. *ppwszPathForServer = pwszPath;
  237. }
  238. return S_OK;
  239. }
  240. //
  241. // Finds an exe name by looking for the first .exe sub string which
  242. // is followed by any of the given delimiter chars or a null.
  243. //
  244. BOOL
  245. FindExeComponent(
  246. IN WCHAR * pwszString,
  247. IN WCHAR * pwszDelimiters,
  248. OUT WCHAR ** ppwszStart,
  249. OUT WCHAR ** ppwszEnd
  250. )
  251. {
  252. WCHAR * pwszLast;
  253. WCHAR * pwszSearch;
  254. WCHAR wszStr[4];
  255. DWORD Delimiters;
  256. Delimiters = lstrlenW( pwszDelimiters ) + 1;
  257. pwszSearch = pwszString;
  258. pwszLast = pwszSearch + lstrlenW( pwszSearch );
  259. for ( ; pwszSearch <= (pwszLast - 4); pwszSearch++ )
  260. {
  261. if ( pwszSearch[0] != L'.' )
  262. continue;
  263. for ( DWORD n = 0; n < Delimiters; n++ )
  264. {
  265. if ( pwszDelimiters[n] == pwszSearch[4] )
  266. {
  267. // Note that there is no lstrnicmpW, so we use memcpy/lstrcmpiW.
  268. memcpy( wszStr, &pwszSearch[1], 3 * sizeof(WCHAR) );
  269. wszStr[3] = 0;
  270. if ( lstrcmpiW( wszStr, L"exe" ) == 0 )
  271. goto FoundExe;
  272. }
  273. }
  274. }
  275. FoundExe:
  276. if ( pwszSearch > (pwszLast - 4) )
  277. return FALSE;
  278. *ppwszEnd = &pwszSearch[4];
  279. for ( ; pwszSearch != pwszString && pwszSearch[-1] != L'\\'; pwszSearch-- )
  280. ;
  281. *ppwszStart = pwszSearch;
  282. return TRUE;
  283. }
  284. //+-------------------------------------------------------------------------
  285. //
  286. // Function: HexStringToDword
  287. //
  288. // Synopsis: Convert a character string hex digits to a DWORD
  289. //
  290. // Arguments: [lpsz] - string to convert
  291. // [Value] - where to put the value
  292. // [cDigits] - number of digits expected
  293. // [chDelim] - delimiter for end of string
  294. //
  295. // Returns: TRUE - string converted to a DWORD
  296. // FALSE - string could not be converted
  297. //
  298. // Algorithm: For each digit in the string, shift the value and
  299. // add the value of the digit to the output value. When
  300. // all the digits are processed, if a delimiter is
  301. // provided, make sure the last character is the delimiter.
  302. //
  303. // History: 22-Apr-93 Ricksa Created
  304. //
  305. // Notes: Lifted from CairOLE sources so that SCM will have no
  306. // dependency on compobj.dll.
  307. //
  308. //--------------------------------------------------------------------------
  309. #if 1 // #ifndef _CHICAGO_
  310. BOOL HexStringToDword(
  311. LPCWSTR FAR& lpsz,
  312. DWORD FAR& Value,
  313. int cDigits,
  314. WCHAR chDelim)
  315. {
  316. int Count;
  317. Value = 0;
  318. for (Count = 0; Count < cDigits; Count++, lpsz++)
  319. {
  320. if (*lpsz >= '0' && *lpsz <= '9')
  321. {
  322. Value = (Value << 4) + *lpsz - '0';
  323. }
  324. else if (*lpsz >= 'A' && *lpsz <= 'F')
  325. {
  326. Value = (Value << 4) + *lpsz - 'A' + 10;
  327. }
  328. else if (*lpsz >= 'a' && *lpsz <= 'f')
  329. {
  330. Value = (Value << 4) + *lpsz - 'a' + 10;
  331. }
  332. else
  333. {
  334. return FALSE;
  335. }
  336. }
  337. if (chDelim != 0)
  338. {
  339. return *lpsz++ == chDelim;
  340. }
  341. return TRUE;
  342. }
  343. #endif
  344. //+-------------------------------------------------------------------------
  345. //
  346. // Function: GUIDFromString
  347. //
  348. // Synopsis: Convert a string in Registry to a GUID.
  349. //
  350. // Arguments: [lpsz] - string from registry
  351. // [pguid] - where to put the guid.
  352. //
  353. // Returns: TRUE - GUID conversion successful
  354. // FALSE - GUID conversion failed.
  355. //
  356. // Algorithm: Convert each part of the GUID string to the
  357. // appropriate structure member in the guid using
  358. // HexStringToDword. If all conversions work return
  359. // TRUE.
  360. //
  361. // History: 22-Apr-93 Ricksa Created
  362. //
  363. // Notes: Lifted from CairOLE sources so that SCM will have no
  364. // dependency on compobj.dll.
  365. //
  366. //--------------------------------------------------------------------------
  367. #if 1 // #ifndef _CHICAGO_
  368. BOOL GUIDFromString(LPCWSTR lpsz, LPGUID pguid)
  369. {
  370. DWORD dw;
  371. if (*lpsz++ != '{')
  372. {
  373. return FALSE;
  374. }
  375. if (!HexStringToDword(lpsz, pguid->Data1, sizeof(DWORD)*2, '-'))
  376. {
  377. return FALSE;
  378. }
  379. if (!HexStringToDword(lpsz, dw, sizeof(WORD)*2, '-'))
  380. {
  381. return FALSE;
  382. }
  383. pguid->Data2 = (WORD)dw;
  384. if (!HexStringToDword(lpsz, dw, sizeof(WORD)*2, '-'))
  385. {
  386. return FALSE;
  387. }
  388. pguid->Data3 = (WORD)dw;
  389. if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
  390. {
  391. return FALSE;
  392. }
  393. pguid->Data4[0] = (BYTE)dw;
  394. if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, '-'))
  395. {
  396. return FALSE;
  397. }
  398. pguid->Data4[1] = (BYTE)dw;
  399. if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
  400. {
  401. return FALSE;
  402. }
  403. pguid->Data4[2] = (BYTE)dw;
  404. if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
  405. {
  406. return FALSE;
  407. }
  408. pguid->Data4[3] = (BYTE)dw;
  409. if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
  410. {
  411. return FALSE;
  412. }
  413. pguid->Data4[4] = (BYTE)dw;
  414. if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
  415. {
  416. return FALSE;
  417. }
  418. pguid->Data4[5] = (BYTE)dw;
  419. if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, 0))
  420. {
  421. return FALSE;
  422. }
  423. pguid->Data4[6] = (BYTE)dw;
  424. if (!HexStringToDword(lpsz, dw, sizeof(BYTE)*2, /*(*/ '}'))
  425. {
  426. return FALSE;
  427. }
  428. pguid->Data4[7] = (BYTE)dw;
  429. return TRUE;
  430. }
  431. #endif