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.

447 lines
14 KiB

  1. /************************************************************/
  2. /* Windows Write, Copyright 1985-1992 Microsoft Corporation */
  3. /************************************************************/
  4. /* register.c - Handles the Win 3.1 registration library.
  5. *
  6. * Created by Microsoft Corporation.
  7. */
  8. #define LSTRING // for lstrcat etc
  9. #include <windows.h>
  10. #include <shellapi.h>
  11. #include "objreg.h"
  12. #include "mw.h"
  13. #include "winddefs.h"
  14. #include "obj.h"
  15. #include "str.h" /* Needed for string resource id */
  16. #include "menudefs.h"
  17. #include "cmddefs.h"
  18. char szClassName[CBPATHMAX];
  19. HKEY hkeyRoot = NULL;
  20. void NEAR PASCAL MakeMenuString(char *szCtrl, char *szMenuStr, char *szVerb, char *szClass, char *szObject);
  21. /* RegInit() - Prepare the registration database for calls.
  22. */
  23. void FAR RegInit(HANDLE hInst)
  24. {
  25. /* this seems to speed up registration operations immensely, but serves
  26. no other purpose */
  27. //RegOpenKey(HKEY_CLASSES_ROOT,NULL,&hkeyRoot);
  28. }
  29. /* RegTerm() - Clean up and terminate the registration library.
  30. */
  31. void FAR RegTerm(void)
  32. {
  33. if (hkeyRoot)
  34. {
  35. RegCloseKey(hkeyRoot);
  36. hkeyRoot = NULL;
  37. }
  38. }
  39. /* RegGetClassId() - Retrieves the string name of a class.
  40. *
  41. * Note: Classes are guaranteed to be in ASCII, but should
  42. * not be used directly as a rule because they might
  43. * be meaningless if running non-English Windows.
  44. */
  45. void FAR RegGetClassId(LPSTR lpstrName, LPSTR lpstrClass) {
  46. DWORD dwSize = KEYNAMESIZE;
  47. if (RegQueryValue(HKEY_CLASSES_ROOT, lpstrClass, (LPSTR)lpstrName, &dwSize))
  48. lstrcpy(lpstrName, lpstrClass);
  49. }
  50. /* RegMakeFilterSpec() - Retrieves class-associated default extensions.
  51. *
  52. * This function returns a filter spec, to be used in the "Change Link"
  53. * standard dialog box, which contains all the default extensions which
  54. * are associated with the given class name. Again, the class names are
  55. * guaranteed to be in ASCII.
  56. *
  57. * Returns: The index nFilterIndex stating which filter item matches the
  58. * extension, or 0 if none is found or -1 if error.
  59. ** *hFilterSpec is allocated and must be freed by caller.
  60. */
  61. int FAR RegMakeFilterSpec(LPSTR lpstrClass, LPSTR lpstrExt, HANDLE *hFilterSpec)
  62. {
  63. DWORD dwSize;
  64. LPSTR lpstrFilterSpec;
  65. char szClass[KEYNAMESIZE];
  66. char szName[KEYNAMESIZE];
  67. char szString[KEYNAMESIZE];
  68. unsigned int i;
  69. int idWhich = 0;
  70. int idFilterIndex = 0;
  71. if (*hFilterSpec == NULL)
  72. {
  73. if ((*hFilterSpec = GlobalAlloc(GMEM_MOVEABLE|GMEM_ZEROINIT,KEYNAMESIZE+16)) == NULL)
  74. return -1;
  75. lpstrFilterSpec = MAKELP(*hFilterSpec,0);
  76. }
  77. RegOpenKey(HKEY_CLASSES_ROOT,NULL,&hkeyRoot);
  78. for (i = 0; !RegEnumKey(HKEY_CLASSES_ROOT, i++, szName, KEYNAMESIZE); )
  79. {
  80. if (*szName == '.' /* Default Extension... */
  81. /* ... so, get the class name */
  82. && (dwSize = KEYNAMESIZE)
  83. && !RegQueryValue(HKEY_CLASSES_ROOT, szName, szClass, &dwSize)
  84. /* ... and if the class name matches (null class is wildcard) */
  85. && (!lpstrClass || !lstrcmpi(lpstrClass, szClass))
  86. /* ... get the class name string */
  87. && (dwSize = KEYNAMESIZE)
  88. && !RegQueryValue(HKEY_CLASSES_ROOT, szClass, szString, &dwSize))
  89. {
  90. int offset;
  91. idWhich++;
  92. /* If the extension matches, save the filter index */
  93. if (lpstrExt && !lstrcmpi(lpstrExt, szName))
  94. idFilterIndex = idWhich;
  95. offset = lpstrFilterSpec - MAKELP(*hFilterSpec,0);
  96. if ((GlobalSize(*hFilterSpec) - offset) <
  97. (lstrlen(szString) + 16))
  98. {
  99. if ((*hFilterSpec = GlobalReAlloc(*hFilterSpec,GlobalSize(*hFilterSpec)+KEYNAMESIZE+16,
  100. GMEM_MOVEABLE|GMEM_ZEROINIT)) == NULL)
  101. {
  102. GlobalFree(*hFilterSpec);
  103. *hFilterSpec = NULL;
  104. idFilterIndex = -1;
  105. break;
  106. }
  107. lpstrFilterSpec = (LPSTR)MAKELP(*hFilterSpec,0) + offset;
  108. }
  109. /* Copy over "<Class Name String> (*<Default Extension>)"
  110. * e.g. "Server Picture (*.PIC)"
  111. */
  112. lstrcpy(lpstrFilterSpec, szString);
  113. lstrcat(lpstrFilterSpec, " (*");
  114. lstrcat(lpstrFilterSpec, szName);
  115. lstrcat(lpstrFilterSpec, ")");
  116. lpstrFilterSpec += lstrlen(lpstrFilterSpec) + 1;
  117. /* Copy over "*<Default Extension>" (e.g. "*.PIC") */
  118. lstrcpy(lpstrFilterSpec, "*");
  119. lstrcat(lpstrFilterSpec, szName);
  120. lpstrFilterSpec += lstrlen(lpstrFilterSpec) + 1;
  121. }
  122. }
  123. /* Add another NULL at the end of the spec (+ 16 accounts for this) */
  124. if (idFilterIndex > -1)
  125. *lpstrFilterSpec = 0;
  126. if (hkeyRoot)
  127. {
  128. RegCloseKey(hkeyRoot);
  129. hkeyRoot = NULL;
  130. }
  131. return idFilterIndex;
  132. }
  133. /* RegCopyClassName() - Returns the ASCII class id from the listbox.
  134. */
  135. BOOL FAR RegCopyClassName(HWND hwndList, LPSTR lpstrClassName) {
  136. BOOL fSuccess = FALSE;
  137. DWORD dwSize = 0L;
  138. HKEY hkeyTemp;
  139. char szClass[KEYNAMESIZE];
  140. char szExec[KEYNAMESIZE];
  141. char szKey[KEYNAMESIZE];
  142. char szName[KEYNAMESIZE];
  143. int i;
  144. int iWhich;
  145. iWhich = (int)SendMessage(hwndList, LB_GETCURSEL, 0, 0L);
  146. SendMessage(hwndList, LB_GETTEXT, iWhich, (DWORD)(LPSTR)szKey);
  147. RegOpenKey(HKEY_CLASSES_ROOT,NULL,&hkeyRoot);
  148. for (i = 0; !fSuccess && !RegEnumKey(HKEY_CLASSES_ROOT, i++, szClass, KEYNAMESIZE); )
  149. if (*szClass != '.') { /* Not default extension... */
  150. /* See if this class really refers to a server */
  151. dwSize = 0;
  152. hkeyTemp = NULL;
  153. lstrcpy(szExec, szClass);
  154. lstrcat(szExec, "\\protocol\\StdFileEditing\\server");
  155. if (!RegOpenKey(HKEY_CLASSES_ROOT, szExec, &hkeyTemp)) {
  156. /* ... get the class name string */
  157. dwSize = KEYNAMESIZE;
  158. if (!RegQueryValue(HKEY_CLASSES_ROOT, szClass, szName, &dwSize)
  159. && !lstrcmp(szName, szKey))
  160. fSuccess = TRUE;
  161. RegCloseKey(hkeyTemp);
  162. }
  163. }
  164. if (fSuccess)
  165. lstrcpy(lpstrClassName, szClass);
  166. if (hkeyRoot)
  167. {
  168. RegCloseKey(hkeyRoot);
  169. hkeyRoot = NULL;
  170. }
  171. return fSuccess;
  172. }
  173. /* RegGetClassNames() - Fills the list box with possible server names.
  174. */
  175. BOOL FAR RegGetClassNames(HWND hwndList) {
  176. BOOL fSuccess = FALSE;
  177. DWORD dwSize = 0L;
  178. HKEY hkeyTemp;
  179. char szClass[KEYNAMESIZE];
  180. char szExec[KEYNAMESIZE];
  181. char szName[KEYNAMESIZE];
  182. int i;
  183. SendMessage(hwndList, LB_RESETCONTENT, 0, 0L);
  184. RegOpenKey(HKEY_CLASSES_ROOT,NULL,&hkeyRoot);
  185. for (i = 0; !RegEnumKey(HKEY_CLASSES_ROOT, i++, szClass, KEYNAMESIZE); )
  186. if (*szClass != '.') { /* Not default extension... */
  187. /* See if this class really refers to a server */
  188. dwSize = 0;
  189. hkeyTemp = NULL;
  190. lstrcpy(szExec, szClass);
  191. lstrcat(szExec, "\\protocol\\StdFileEditing\\server");
  192. if (!RegOpenKey(HKEY_CLASSES_ROOT, szExec, &hkeyTemp)) {
  193. /* ... get the class name string */
  194. dwSize = KEYNAMESIZE;
  195. if (!RegQueryValue(HKEY_CLASSES_ROOT, szClass, szName, &dwSize)) {
  196. SendMessage(hwndList, LB_ADDSTRING, 0, (DWORD)(LPSTR)szName);
  197. fSuccess = TRUE;
  198. }
  199. RegCloseKey(hkeyTemp);
  200. }
  201. }
  202. if (hkeyRoot)
  203. {
  204. RegCloseKey(hkeyRoot);
  205. hkeyRoot = NULL;
  206. }
  207. return fSuccess;
  208. }
  209. void ObjUpdateMenuVerbs( HMENU hMenu )
  210. {
  211. int cObjects;
  212. extern struct SEL selCur;
  213. extern char szOPropMenuStr[];
  214. extern char szPPropMenuStr[];
  215. extern BOOL vfOutOfMemory;
  216. char szBuffer[cchMaxSz];
  217. char szWordOrder2[10], szWordOrder3[10];
  218. if (vfOutOfMemory)
  219. {
  220. EnableMenuItem(hMenu, EDITMENUPOS, MF_GRAYED|MF_BYPOSITION);
  221. return;
  222. }
  223. LoadString(hINSTANCE, IDSTRPopupVerbs, szWordOrder2, sizeof(szWordOrder2));
  224. LoadString(hINSTANCE, IDSTRSingleVerb, szWordOrder3, sizeof(szWordOrder3));
  225. DeleteMenu(hMenu, EDITMENUPOS, MF_BYPOSITION);
  226. /** Cases:
  227. 0) 0 objects selected
  228. 1) 1 object selected
  229. a) object supports 0 verbs "Edit <Object Class> Object"
  230. b) object supports more than 1 verb "<Object Class> Object" => verbs
  231. 2) more than 1 object selected "Objects"
  232. Use the VerbMenu strings to determine the order in which these words
  233. should appear in the menu string (for localization).
  234. **/
  235. /* how many objects are selected? */
  236. cObjects = ObjSetSelectionType(docCur,selCur.cpFirst, selCur.cpLim);
  237. /* must be only an object, not text in selection */
  238. if (cObjects == 1)
  239. {
  240. ObjCachePara(docCur,selCur.cpFirst);
  241. if (!ObjQueryCpIsObject(docCur,selCur.cpFirst))
  242. cObjects = 0;
  243. }
  244. if ((cObjects == -1) // error
  245. || (cObjects == 0)
  246. || (cObjects > 1))
  247. {
  248. wsprintf(szBuffer, "%s", (LPSTR)((cObjects > 1) ? szPPropMenuStr : szOPropMenuStr));
  249. InsertMenu(hMenu, EDITMENUPOS, MF_BYPOSITION,imiVerb,szBuffer);
  250. /*
  251. Spec says if > 1 then optionally should enable if all servers
  252. are of the same class. I'm opting not to implement. (9.27.91) v-dougk
  253. */
  254. EnableMenuItem(hMenu, EDITMENUPOS, MF_GRAYED | MF_BYPOSITION);
  255. #if 0
  256. else // > 1
  257. {
  258. EnableMenuItem(hMenu, EDITMENUPOS,
  259. (((OBJ_SELECTIONTYPE == EMBEDDED) || (OBJ_SELECTIONTYPE == LINK))
  260. ? MF_ENABLED : MF_GRAYED) | MF_BYPOSITION);
  261. }
  262. #endif
  263. return;
  264. }
  265. else // 1 object selected
  266. {
  267. OBJPICINFO picInfo;
  268. /** CASES:
  269. object supports 0 verbs "Edit <Object Class> Object"
  270. object supports more than 1 verb "<Object Class> Object" => verbs
  271. **/
  272. RegOpenKey(HKEY_CLASSES_ROOT,NULL,&hkeyRoot);
  273. GetPicInfo(selCur.cpFirst,selCur.cpFirst + cchPICINFOX, docCur, &picInfo);
  274. if ((otOBJ_QUERY_TYPE(&picInfo) == EMBEDDED) ||
  275. (otOBJ_QUERY_TYPE(&picInfo) == LINK))
  276. {
  277. HANDLE hData=NULL;
  278. LPSTR lpstrData;
  279. OLESTATUS olestat;
  280. olestat = OleGetData(lpOBJ_QUERY_OBJECT(&picInfo),
  281. otOBJ_QUERY_TYPE(&picInfo) == LINK? vcfLink: vcfOwnerLink,
  282. &hData);
  283. if ((olestat == OLE_WARN_DELETE_DATA) || (olestat == OLE_OK))
  284. {
  285. HKEY hKeyVerb;
  286. DWORD dwSize = KEYNAMESIZE;
  287. char szClass[KEYNAMESIZE];
  288. char szVerb[KEYNAMESIZE];
  289. HANDLE hPopupNew=NULL;
  290. lpstrData = MAKELP(hData,0);
  291. /* Both link formats are: "szClass0szDocument0szItem00" */
  292. /* get real language class of object in szClass for menu */
  293. if (RegQueryValue(HKEY_CLASSES_ROOT, lpstrData, szClass, &dwSize))
  294. lstrcpy(szClass, lpstrData); /* if above call failed */
  295. if (olestat == OLE_WARN_DELETE_DATA)
  296. GlobalFree(hData);
  297. /* append class key */
  298. for (vcVerbs=0; ;++vcVerbs)
  299. {
  300. dwSize = KEYNAMESIZE;
  301. wsprintf(szBuffer, "%s\\protocol\\StdFileEditing\\verb\\%d", (LPSTR)lpstrData,vcVerbs);
  302. if (RegQueryValue(HKEY_CLASSES_ROOT, szBuffer, szVerb, &dwSize))
  303. break;
  304. if (hPopupNew == NULL)
  305. hPopupNew = CreatePopupMenu();
  306. InsertMenu(hPopupNew, -1, MF_BYPOSITION, imiVerb+vcVerbs+1, szVerb);
  307. }
  308. if (vcVerbs == 0)
  309. {
  310. LoadString(hINSTANCE, IDSTREdit, szVerb, sizeof(szVerb));
  311. MakeMenuString(szWordOrder3, szBuffer, szVerb, szClass, szOPropMenuStr);
  312. InsertMenu(hMenu, EDITMENUPOS, MF_BYPOSITION, imiVerbPlay, szBuffer);
  313. }
  314. else if (vcVerbs == 1)
  315. {
  316. MakeMenuString(szWordOrder3, szBuffer, szVerb, szClass, szOPropMenuStr);
  317. InsertMenu(hMenu, EDITMENUPOS, MF_BYPOSITION, imiVerbPlay, szBuffer);
  318. DestroyMenu(hPopupNew);
  319. }
  320. else // > 1 verbs
  321. {
  322. MakeMenuString(szWordOrder2, szBuffer, NULL, szClass, szOPropMenuStr);
  323. InsertMenu(hMenu, EDITMENUPOS, MF_BYPOSITION | MF_POPUP,
  324. hPopupNew, szBuffer);
  325. }
  326. EnableMenuItem(hMenu, EDITMENUPOS, MF_ENABLED|MF_BYPOSITION);
  327. if (hkeyRoot)
  328. {
  329. RegCloseKey(hkeyRoot);
  330. hkeyRoot = NULL;
  331. }
  332. return;
  333. }
  334. else
  335. ObjError(olestat);
  336. }
  337. }
  338. /* error if got to here */
  339. wsprintf(szBuffer, "%s", (LPSTR)szOPropMenuStr);
  340. InsertMenu(hMenu, EDITMENUPOS, MF_BYPOSITION,NULL,szBuffer);
  341. EnableMenuItem(hMenu, EDITMENUPOS, MF_GRAYED|MF_BYPOSITION);
  342. if (hkeyRoot)
  343. {
  344. RegCloseKey(hkeyRoot);
  345. hkeyRoot = NULL;
  346. }
  347. }
  348. void NEAR PASCAL MakeMenuString(char *szCtrl, char *szMenuStr, char *szVerb, char *szClass, char *szObject)
  349. {
  350. char *pStr;
  351. register char c;
  352. while (c = *szCtrl++)
  353. {
  354. switch(c)
  355. {
  356. case 'c': // class
  357. case 'C': // class
  358. pStr = szClass;
  359. break;
  360. case 'v': // class
  361. case 'V': // class
  362. pStr = szVerb;
  363. break;
  364. case 'o': // object
  365. case 'O': // object
  366. pStr = szObject;
  367. break;
  368. default:
  369. *szMenuStr++ = c;
  370. *szMenuStr = '\0'; // just in case
  371. continue;
  372. }
  373. if (pStr) // should always be true
  374. {
  375. lstrcpy(szMenuStr,pStr);
  376. szMenuStr += lstrlen(pStr); // point to '\0'
  377. }
  378. }
  379. }
  380.