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.

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