class.c 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260
  1. /*
  2. * Window classes functions
  3. *
  4. * Copyright 1993, 1996, 2003 Alexandre Julliard
  5. * Copyright 1998 Juergen Schmied (jsch)
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. */
  21. #include "config.h"
  22. #include "wine/port.h"
  23. #include <assert.h>
  24. #include <stdarg.h>
  25. #include <stdlib.h>
  26. #include <string.h>
  27. #include "winerror.h"
  28. #include "windef.h"
  29. #include "winbase.h"
  30. #include "wingdi.h"
  31. #include "wine/winuser16.h"
  32. #include "wine/unicode.h"
  33. #include "win.h"
  34. #include "user_private.h"
  35. #include "controls.h"
  36. #include "dce.h"
  37. #include "winproc.h"
  38. #include "wine/server.h"
  39. #include "wine/list.h"
  40. #include "wine/debug.h"
  41. WINE_DEFAULT_DEBUG_CHANNEL(class);
  42. typedef struct tagCLASS
  43. {
  44. struct list entry; /* Entry in class list */
  45. UINT style; /* Class style */
  46. BOOL local; /* Local class? */
  47. WNDPROC winprocA; /* Window procedure (ASCII) */
  48. WNDPROC winprocW; /* Window procedure (Unicode) */
  49. INT cbClsExtra; /* Class extra bytes */
  50. INT cbWndExtra; /* Window extra bytes */
  51. LPWSTR menuName; /* Default menu name (Unicode followed by ASCII) */
  52. SEGPTR segMenuName; /* Default menu name as SEGPTR */
  53. struct tagDCE *dce; /* Class DCE (if CS_CLASSDC) */
  54. HINSTANCE hInstance; /* Module that created the task */
  55. HICON hIcon; /* Default icon */
  56. HICON hIconSm; /* Default small icon */
  57. HCURSOR hCursor; /* Default cursor */
  58. HBRUSH hbrBackground; /* Default background */
  59. ATOM atomName; /* Name of the class */
  60. } CLASS;
  61. static struct list class_list = LIST_INIT( class_list );
  62. static CLASS *desktop_class;
  63. #define CLASS_OTHER_PROCESS ((CLASS *)1)
  64. /***********************************************************************
  65. * get_class_ptr
  66. */
  67. static CLASS *get_class_ptr( HWND hwnd, BOOL write_access )
  68. {
  69. WND *ptr = WIN_GetPtr( hwnd );
  70. if (ptr)
  71. {
  72. if (ptr != WND_OTHER_PROCESS) return ptr->class;
  73. if (write_access && IsWindow( hwnd )) /* check other processes */
  74. {
  75. /* modifying classes in other processes is not allowed */
  76. SetLastError( ERROR_ACCESS_DENIED );
  77. return NULL;
  78. }
  79. return CLASS_OTHER_PROCESS;
  80. }
  81. SetLastError( ERROR_INVALID_WINDOW_HANDLE );
  82. return NULL;
  83. }
  84. /***********************************************************************
  85. * release_class_ptr
  86. */
  87. inline static void release_class_ptr( CLASS *ptr )
  88. {
  89. USER_Unlock();
  90. }
  91. /***********************************************************************
  92. * set_server_info
  93. *
  94. * Set class info with the wine server.
  95. */
  96. static BOOL set_server_info( HWND hwnd, INT offset, LONG newval )
  97. {
  98. BOOL ret;
  99. SERVER_START_REQ( set_class_info )
  100. {
  101. req->window = hwnd;
  102. req->extra_offset = -1;
  103. switch(offset)
  104. {
  105. case GCW_ATOM:
  106. req->flags = SET_CLASS_ATOM;
  107. req->atom = newval;
  108. case GCL_STYLE:
  109. req->flags = SET_CLASS_STYLE;
  110. req->style = newval;
  111. break;
  112. case GCL_CBWNDEXTRA:
  113. req->flags = SET_CLASS_WINEXTRA;
  114. req->win_extra = newval;
  115. break;
  116. case GCL_HMODULE:
  117. req->flags = SET_CLASS_INSTANCE;
  118. req->instance = (void *)newval;
  119. break;
  120. default:
  121. assert( offset >= 0 );
  122. req->flags = SET_CLASS_EXTRA;
  123. req->extra_offset = offset;
  124. req->extra_size = sizeof(newval);
  125. memcpy( &req->extra_value, &newval, sizeof(newval) );
  126. break;
  127. }
  128. ret = !wine_server_call_err( req );
  129. }
  130. SERVER_END_REQ;
  131. return ret;
  132. }
  133. /***********************************************************************
  134. * CLASS_GetProc
  135. *
  136. * Get the class winproc for a given proc type
  137. */
  138. static WNDPROC16 CLASS_GetProc( CLASS *classPtr, WINDOWPROCTYPE type )
  139. {
  140. WNDPROC proc = classPtr->winprocA;
  141. if (classPtr->winprocW)
  142. {
  143. /* if we have a Unicode proc, use it if we have no ASCII proc
  144. * or if we have both and Unicode was requested
  145. */
  146. if (!proc || type == WIN_PROC_32W) proc = classPtr->winprocW;
  147. }
  148. return WINPROC_GetProc( proc, type );
  149. }
  150. /***********************************************************************
  151. * CLASS_SetProc
  152. *
  153. * Set the class winproc for a given proc type.
  154. * Returns the previous window proc.
  155. */
  156. static WNDPROC16 CLASS_SetProc( CLASS *classPtr, WNDPROC newproc, WINDOWPROCTYPE type )
  157. {
  158. WNDPROC *proc = &classPtr->winprocA;
  159. WNDPROC16 ret;
  160. if (classPtr->winprocW)
  161. {
  162. /* if we have a Unicode proc, use it if we have no ASCII proc
  163. * or if we have both and Unicode was requested
  164. */
  165. if (!*proc || type == WIN_PROC_32W) proc = &classPtr->winprocW;
  166. }
  167. ret = WINPROC_GetProc( *proc, type );
  168. *proc = WINPROC_AllocProc( newproc, type );
  169. /* now clear the one that we didn't set */
  170. if (classPtr->winprocA && classPtr->winprocW)
  171. {
  172. if (proc == &classPtr->winprocA)
  173. classPtr->winprocW = 0;
  174. else
  175. classPtr->winprocA = 0;
  176. }
  177. return ret;
  178. }
  179. /***********************************************************************
  180. * CLASS_GetMenuNameA
  181. *
  182. * Get the menu name as a ASCII string.
  183. */
  184. inline static LPSTR CLASS_GetMenuNameA( CLASS *classPtr )
  185. {
  186. if (!HIWORD(classPtr->menuName)) return (LPSTR)classPtr->menuName;
  187. return (LPSTR)(classPtr->menuName + strlenW(classPtr->menuName) + 1);
  188. }
  189. /***********************************************************************
  190. * CLASS_GetMenuName16
  191. *
  192. * Get the menu name as a SEGPTR.
  193. */
  194. inline static SEGPTR CLASS_GetMenuName16( CLASS *classPtr )
  195. {
  196. if (!HIWORD(classPtr->menuName)) return (SEGPTR)classPtr->menuName;
  197. if (!classPtr->segMenuName)
  198. classPtr->segMenuName = MapLS( CLASS_GetMenuNameA(classPtr) );
  199. return classPtr->segMenuName;
  200. }
  201. /***********************************************************************
  202. * CLASS_GetMenuNameW
  203. *
  204. * Get the menu name as a Unicode string.
  205. */
  206. inline static LPWSTR CLASS_GetMenuNameW( CLASS *classPtr )
  207. {
  208. return classPtr->menuName;
  209. }
  210. /***********************************************************************
  211. * CLASS_SetMenuNameA
  212. *
  213. * Set the menu name in a class structure by copying the string.
  214. */
  215. static void CLASS_SetMenuNameA( CLASS *classPtr, LPCSTR name )
  216. {
  217. UnMapLS( classPtr->segMenuName );
  218. classPtr->segMenuName = 0;
  219. if (HIWORD(classPtr->menuName)) HeapFree( GetProcessHeap(), 0, classPtr->menuName );
  220. if (HIWORD(name))
  221. {
  222. DWORD lenA = strlen(name) + 1;
  223. DWORD lenW = MultiByteToWideChar( CP_ACP, 0, name, lenA, NULL, 0 );
  224. classPtr->menuName = HeapAlloc( GetProcessHeap(), 0, lenA + lenW*sizeof(WCHAR) );
  225. MultiByteToWideChar( CP_ACP, 0, name, lenA, classPtr->menuName, lenW );
  226. memcpy( classPtr->menuName + lenW, name, lenA );
  227. }
  228. else classPtr->menuName = (LPWSTR)name;
  229. }
  230. /***********************************************************************
  231. * CLASS_SetMenuNameW
  232. *
  233. * Set the menu name in a class structure by copying the string.
  234. */
  235. static void CLASS_SetMenuNameW( CLASS *classPtr, LPCWSTR name )
  236. {
  237. UnMapLS( classPtr->segMenuName );
  238. classPtr->segMenuName = 0;
  239. if (HIWORD(classPtr->menuName)) HeapFree( GetProcessHeap(), 0, classPtr->menuName );
  240. if (HIWORD(name))
  241. {
  242. DWORD lenW = strlenW(name) + 1;
  243. DWORD lenA = WideCharToMultiByte( CP_ACP, 0, name, lenW, NULL, 0, NULL, NULL );
  244. classPtr->menuName = HeapAlloc( GetProcessHeap(), 0, lenA + lenW*sizeof(WCHAR) );
  245. memcpy( classPtr->menuName, name, lenW*sizeof(WCHAR) );
  246. WideCharToMultiByte( CP_ACP, 0, name, lenW,
  247. (char *)(classPtr->menuName + lenW), lenA, NULL, NULL );
  248. }
  249. else classPtr->menuName = (LPWSTR)name;
  250. }
  251. /***********************************************************************
  252. * CLASS_FreeClass
  253. *
  254. * Free a class structure.
  255. */
  256. static void CLASS_FreeClass( CLASS *classPtr )
  257. {
  258. TRACE("%p\n", classPtr);
  259. USER_Lock();
  260. list_remove( &classPtr->entry );
  261. if (classPtr->dce) DCE_FreeDCE( classPtr->dce );
  262. if (classPtr->hbrBackground > (HBRUSH)(COLOR_GRADIENTINACTIVECAPTION + 1))
  263. DeleteObject( classPtr->hbrBackground );
  264. UnMapLS( classPtr->segMenuName );
  265. HeapFree( GetProcessHeap(), 0, classPtr->menuName );
  266. HeapFree( GetProcessHeap(), 0, classPtr );
  267. USER_Unlock();
  268. }
  269. /***********************************************************************
  270. * CLASS_FreeModuleClasses
  271. */
  272. void CLASS_FreeModuleClasses( HMODULE16 hModule )
  273. {
  274. struct list *ptr, *next;
  275. TRACE("0x%08x\n", hModule);
  276. USER_Lock();
  277. for (ptr = list_head( &class_list ); ptr; ptr = next)
  278. {
  279. CLASS *class = LIST_ENTRY( ptr, CLASS, entry );
  280. next = list_next( &class_list, ptr );
  281. if (class->hInstance == HINSTANCE_32(hModule))
  282. {
  283. BOOL ret;
  284. SERVER_START_REQ( destroy_class )
  285. {
  286. req->atom = class->atomName;
  287. req->instance = class->hInstance;
  288. ret = !wine_server_call_err( req );
  289. }
  290. SERVER_END_REQ;
  291. if (ret) CLASS_FreeClass( class );
  292. }
  293. }
  294. USER_Unlock();
  295. }
  296. /***********************************************************************
  297. * CLASS_FindClassByAtom
  298. *
  299. * Return a pointer to the class.
  300. * hinstance has been normalized by the caller.
  301. */
  302. static CLASS *CLASS_FindClassByAtom( ATOM atom, HINSTANCE hinstance )
  303. {
  304. struct list *ptr;
  305. USER_Lock();
  306. LIST_FOR_EACH( ptr, &class_list )
  307. {
  308. CLASS *class = LIST_ENTRY( ptr, CLASS, entry );
  309. if (class->atomName != atom) continue;
  310. if (!hinstance || !class->local || class->hInstance == hinstance)
  311. {
  312. TRACE("0x%04x %p -> %p\n", atom, hinstance, class);
  313. return class;
  314. }
  315. }
  316. USER_Unlock();
  317. TRACE("0x%04x %p -> not found\n", atom, hinstance);
  318. return NULL;
  319. }
  320. /***********************************************************************
  321. * CLASS_RegisterClass
  322. *
  323. * The real RegisterClass() functionality.
  324. * The atom is deleted no matter what.
  325. */
  326. static CLASS *CLASS_RegisterClass( ATOM atom, HINSTANCE hInstance, BOOL local,
  327. DWORD style, INT classExtra, INT winExtra )
  328. {
  329. CLASS *classPtr;
  330. BOOL ret;
  331. TRACE("atom=0x%x hinst=%p style=0x%lx clExtr=0x%x winExtr=0x%x\n",
  332. atom, hInstance, style, classExtra, winExtra );
  333. /* Fix the extra bytes value */
  334. if (classExtra < 0) classExtra = 0;
  335. else if (classExtra > 40) /* Extra bytes are limited to 40 in Win32 */
  336. WARN("Class extra bytes %d is > 40\n", classExtra);
  337. if (winExtra < 0) winExtra = 0;
  338. else if (winExtra > 40) /* Extra bytes are limited to 40 in Win32 */
  339. WARN("Win extra bytes %d is > 40\n", winExtra );
  340. classPtr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(CLASS) + classExtra );
  341. if (!classPtr)
  342. {
  343. GlobalDeleteAtom( atom );
  344. return NULL;
  345. }
  346. SERVER_START_REQ( create_class )
  347. {
  348. req->local = local;
  349. req->atom = atom;
  350. req->style = style;
  351. req->instance = hInstance;
  352. req->extra = classExtra;
  353. req->win_extra = winExtra;
  354. req->client_ptr = classPtr;
  355. ret = !wine_server_call_err( req );
  356. }
  357. SERVER_END_REQ;
  358. GlobalDeleteAtom( atom ); /* the server increased the atom ref count */
  359. if (!ret)
  360. {
  361. HeapFree( GetProcessHeap(), 0, classPtr );
  362. return NULL;
  363. }
  364. classPtr->style = style;
  365. classPtr->local = local;
  366. classPtr->cbWndExtra = winExtra;
  367. classPtr->cbClsExtra = classExtra;
  368. classPtr->hInstance = hInstance;
  369. classPtr->atomName = atom;
  370. classPtr->dce = (style & CS_CLASSDC) ? DCE_AllocDCE( 0, DCE_CLASS_DC ) : NULL;
  371. /* Other non-null values must be set by caller */
  372. USER_Lock();
  373. if (local) list_add_head( &class_list, &classPtr->entry );
  374. else list_add_tail( &class_list, &classPtr->entry );
  375. return classPtr;
  376. }
  377. /***********************************************************************
  378. * register_builtin
  379. *
  380. * Register a builtin control class.
  381. * This allows having both ASCII and Unicode winprocs for the same class.
  382. */
  383. static CLASS *register_builtin( const struct builtin_class_descr *descr )
  384. {
  385. ATOM atom;
  386. CLASS *classPtr;
  387. if (!(atom = GlobalAddAtomA( descr->name ))) return 0;
  388. if (!(classPtr = CLASS_RegisterClass( atom, user32_module, FALSE,
  389. descr->style, 0, descr->extra ))) return 0;
  390. classPtr->hCursor = LoadCursorA( 0, (LPSTR)descr->cursor );
  391. classPtr->hbrBackground = descr->brush;
  392. if (descr->procA) classPtr->winprocA = WINPROC_AllocProc( descr->procA, WIN_PROC_32A );
  393. if (descr->procW) classPtr->winprocW = WINPROC_AllocProc( descr->procW, WIN_PROC_32W );
  394. release_class_ptr( classPtr );
  395. return classPtr;
  396. }
  397. /***********************************************************************
  398. * CLASS_RegisterBuiltinClasses
  399. */
  400. void CLASS_RegisterBuiltinClasses(void)
  401. {
  402. extern const struct builtin_class_descr BUTTON_builtin_class;
  403. extern const struct builtin_class_descr COMBO_builtin_class;
  404. extern const struct builtin_class_descr COMBOLBOX_builtin_class;
  405. extern const struct builtin_class_descr DIALOG_builtin_class;
  406. extern const struct builtin_class_descr DESKTOP_builtin_class;
  407. extern const struct builtin_class_descr EDIT_builtin_class;
  408. extern const struct builtin_class_descr ICONTITLE_builtin_class;
  409. extern const struct builtin_class_descr LISTBOX_builtin_class;
  410. extern const struct builtin_class_descr MDICLIENT_builtin_class;
  411. extern const struct builtin_class_descr MENU_builtin_class;
  412. extern const struct builtin_class_descr SCROLL_builtin_class;
  413. extern const struct builtin_class_descr STATIC_builtin_class;
  414. desktop_class = register_builtin( &DESKTOP_builtin_class );
  415. register_builtin( &BUTTON_builtin_class );
  416. register_builtin( &COMBO_builtin_class );
  417. register_builtin( &COMBOLBOX_builtin_class );
  418. register_builtin( &DIALOG_builtin_class );
  419. register_builtin( &EDIT_builtin_class );
  420. register_builtin( &ICONTITLE_builtin_class );
  421. register_builtin( &LISTBOX_builtin_class );
  422. register_builtin( &MDICLIENT_builtin_class );
  423. register_builtin( &MENU_builtin_class );
  424. register_builtin( &SCROLL_builtin_class );
  425. register_builtin( &STATIC_builtin_class );
  426. }
  427. /***********************************************************************
  428. * CLASS_AddWindow
  429. *
  430. * Add a new window using this class, and set the necessary
  431. * information inside the window structure.
  432. */
  433. void CLASS_AddWindow( CLASS *class, WND *win, WINDOWPROCTYPE type )
  434. {
  435. if (!class) class = desktop_class;
  436. if (type == WIN_PROC_32W)
  437. {
  438. if (!(win->winproc = class->winprocW)) win->winproc = class->winprocA;
  439. }
  440. else
  441. {
  442. if (!(win->winproc = class->winprocA)) win->winproc = class->winprocW;
  443. }
  444. win->class = class;
  445. win->clsStyle = class->style;
  446. win->dce = class->dce;
  447. }
  448. /***********************************************************************
  449. * RegisterClassA (USER32.@)
  450. * RETURNS
  451. * >0: Unique identifier
  452. * 0: Failure
  453. */
  454. ATOM WINAPI RegisterClassA( const WNDCLASSA* wc ) /* [in] Address of structure with class data */
  455. {
  456. WNDCLASSEXA wcex;
  457. wcex.cbSize = sizeof(wcex);
  458. wcex.style = wc->style;
  459. wcex.lpfnWndProc = wc->lpfnWndProc;
  460. wcex.cbClsExtra = wc->cbClsExtra;
  461. wcex.cbWndExtra = wc->cbWndExtra;
  462. wcex.hInstance = wc->hInstance;
  463. wcex.hIcon = wc->hIcon;
  464. wcex.hCursor = wc->hCursor;
  465. wcex.hbrBackground = wc->hbrBackground;
  466. wcex.lpszMenuName = wc->lpszMenuName;
  467. wcex.lpszClassName = wc->lpszClassName;
  468. wcex.hIconSm = 0;
  469. return RegisterClassExA( &wcex );
  470. }
  471. /***********************************************************************
  472. * RegisterClassW (USER32.@)
  473. */
  474. ATOM WINAPI RegisterClassW( const WNDCLASSW* wc )
  475. {
  476. WNDCLASSEXW wcex;
  477. wcex.cbSize = sizeof(wcex);
  478. wcex.style = wc->style;
  479. wcex.lpfnWndProc = wc->lpfnWndProc;
  480. wcex.cbClsExtra = wc->cbClsExtra;
  481. wcex.cbWndExtra = wc->cbWndExtra;
  482. wcex.hInstance = wc->hInstance;
  483. wcex.hIcon = wc->hIcon;
  484. wcex.hCursor = wc->hCursor;
  485. wcex.hbrBackground = wc->hbrBackground;
  486. wcex.lpszMenuName = wc->lpszMenuName;
  487. wcex.lpszClassName = wc->lpszClassName;
  488. wcex.hIconSm = 0;
  489. return RegisterClassExW( &wcex );
  490. }
  491. /***********************************************************************
  492. * RegisterClassExA (USER32.@)
  493. */
  494. ATOM WINAPI RegisterClassExA( const WNDCLASSEXA* wc )
  495. {
  496. ATOM atom;
  497. CLASS *classPtr;
  498. HINSTANCE instance;
  499. if (wc->hInstance == user32_module)
  500. {
  501. /* we can't register a class for user32 */
  502. SetLastError( ERROR_INVALID_PARAMETER );
  503. return 0;
  504. }
  505. if (!(instance = wc->hInstance)) instance = GetModuleHandleW( NULL );
  506. if (!(atom = GlobalAddAtomA( wc->lpszClassName ))) return 0;
  507. if (!(classPtr = CLASS_RegisterClass( atom, instance, !(wc->style & CS_GLOBALCLASS),
  508. wc->style, wc->cbClsExtra, wc->cbWndExtra )))
  509. return 0;
  510. TRACE("atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n",
  511. atom, wc->lpfnWndProc, instance, wc->hbrBackground,
  512. wc->style, wc->cbClsExtra, wc->cbWndExtra, classPtr );
  513. classPtr->hIcon = wc->hIcon;
  514. classPtr->hIconSm = wc->hIconSm;
  515. classPtr->hCursor = wc->hCursor;
  516. classPtr->hbrBackground = wc->hbrBackground;
  517. classPtr->winprocA = WINPROC_AllocProc( wc->lpfnWndProc, WIN_PROC_32A );
  518. CLASS_SetMenuNameA( classPtr, wc->lpszMenuName );
  519. release_class_ptr( classPtr );
  520. return atom;
  521. }
  522. /***********************************************************************
  523. * RegisterClassExW (USER32.@)
  524. */
  525. ATOM WINAPI RegisterClassExW( const WNDCLASSEXW* wc )
  526. {
  527. ATOM atom;
  528. CLASS *classPtr;
  529. HINSTANCE instance;
  530. if (wc->hInstance == user32_module)
  531. {
  532. /* we can't register a class for user32 */
  533. SetLastError( ERROR_INVALID_PARAMETER );
  534. return 0;
  535. }
  536. if (!(instance = wc->hInstance)) instance = GetModuleHandleW( NULL );
  537. if (!(atom = GlobalAddAtomW( wc->lpszClassName ))) return 0;
  538. if (!(classPtr = CLASS_RegisterClass( atom, instance, !(wc->style & CS_GLOBALCLASS),
  539. wc->style, wc->cbClsExtra, wc->cbWndExtra )))
  540. return 0;
  541. TRACE("atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n",
  542. atom, wc->lpfnWndProc, instance, wc->hbrBackground,
  543. wc->style, wc->cbClsExtra, wc->cbWndExtra, classPtr );
  544. classPtr->hIcon = wc->hIcon;
  545. classPtr->hIconSm = wc->hIconSm;
  546. classPtr->hCursor = wc->hCursor;
  547. classPtr->hbrBackground = wc->hbrBackground;
  548. classPtr->winprocW = WINPROC_AllocProc( wc->lpfnWndProc, WIN_PROC_32W );
  549. CLASS_SetMenuNameW( classPtr, wc->lpszMenuName );
  550. release_class_ptr( classPtr );
  551. return atom;
  552. }
  553. /***********************************************************************
  554. * UnregisterClassA (USER32.@)
  555. */
  556. BOOL WINAPI UnregisterClassA( LPCSTR className, HINSTANCE hInstance )
  557. {
  558. ATOM atom = HIWORD(className) ? GlobalFindAtomA( className ) : LOWORD(className);
  559. return UnregisterClassW( MAKEINTATOMW(atom), hInstance );
  560. }
  561. /***********************************************************************
  562. * UnregisterClassW (USER32.@)
  563. */
  564. BOOL WINAPI UnregisterClassW( LPCWSTR className, HINSTANCE hInstance )
  565. {
  566. CLASS *classPtr = NULL;
  567. ATOM atom = HIWORD(className) ? GlobalFindAtomW( className ) : LOWORD(className);
  568. TRACE("%s %p %x\n",debugstr_w(className), hInstance, atom);
  569. if (!atom)
  570. {
  571. SetLastError( ERROR_CLASS_DOES_NOT_EXIST );
  572. return FALSE;
  573. }
  574. SERVER_START_REQ( destroy_class )
  575. {
  576. req->atom = atom;
  577. req->instance = hInstance;
  578. if (!wine_server_call_err( req )) classPtr = reply->client_ptr;
  579. }
  580. SERVER_END_REQ;
  581. if (classPtr) CLASS_FreeClass( classPtr );
  582. return (classPtr != NULL);
  583. }
  584. /***********************************************************************
  585. * GetClassWord (USER32.@)
  586. */
  587. WORD WINAPI GetClassWord( HWND hwnd, INT offset )
  588. {
  589. CLASS *class;
  590. WORD retvalue = 0;
  591. if (offset < 0) return GetClassLongA( hwnd, offset );
  592. TRACE("%p %x\n",hwnd, offset);
  593. if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
  594. if (class == CLASS_OTHER_PROCESS)
  595. {
  596. SERVER_START_REQ( set_class_info )
  597. {
  598. req->window = hwnd;
  599. req->flags = 0;
  600. req->extra_offset = offset;
  601. req->extra_size = sizeof(retvalue);
  602. if (!wine_server_call_err( req ))
  603. memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
  604. }
  605. SERVER_END_REQ;
  606. return retvalue;
  607. }
  608. if (offset <= class->cbClsExtra - sizeof(WORD))
  609. memcpy( &retvalue, (char *)(class + 1) + offset, sizeof(retvalue) );
  610. else
  611. SetLastError( ERROR_INVALID_INDEX );
  612. release_class_ptr( class );
  613. return retvalue;
  614. }
  615. /***********************************************************************
  616. * GetClassLong (USER.131)
  617. */
  618. LONG WINAPI GetClassLong16( HWND16 hwnd16, INT16 offset )
  619. {
  620. CLASS *class;
  621. LONG ret;
  622. HWND hwnd = (HWND)(ULONG_PTR)hwnd16; /* no need for full handle */
  623. TRACE("%p %d\n",hwnd, offset);
  624. switch( offset )
  625. {
  626. case GCL_WNDPROC:
  627. if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
  628. if (class == CLASS_OTHER_PROCESS) break;
  629. ret = (LONG)CLASS_GetProc( class, WIN_PROC_16 );
  630. release_class_ptr( class );
  631. return ret;
  632. case GCL_MENUNAME:
  633. if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
  634. if (class == CLASS_OTHER_PROCESS) break;
  635. ret = (LONG)CLASS_GetMenuName16( class );
  636. release_class_ptr( class );
  637. return ret;
  638. default:
  639. return GetClassLongA( hwnd, offset );
  640. }
  641. FIXME( "offset %d not supported on other process window %p\n", offset, hwnd );
  642. SetLastError( ERROR_INVALID_HANDLE );
  643. return 0;
  644. }
  645. /***********************************************************************
  646. * GetClassLongW (USER32.@)
  647. */
  648. LONG WINAPI GetClassLongW( HWND hwnd, INT offset )
  649. {
  650. CLASS *class;
  651. LONG retvalue = 0;
  652. TRACE("%p %d\n", hwnd, offset);
  653. if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
  654. if (class == CLASS_OTHER_PROCESS)
  655. {
  656. SERVER_START_REQ( set_class_info )
  657. {
  658. req->window = hwnd;
  659. req->flags = 0;
  660. req->extra_offset = (offset >= 0) ? offset : -1;
  661. req->extra_size = (offset >= 0) ? sizeof(retvalue) : 0;
  662. if (!wine_server_call_err( req ))
  663. {
  664. switch(offset)
  665. {
  666. case GCL_HBRBACKGROUND:
  667. case GCL_HCURSOR:
  668. case GCL_HICON:
  669. case GCL_HICONSM:
  670. case GCL_WNDPROC:
  671. case GCL_MENUNAME:
  672. FIXME( "offset %d not supported on other process window %p\n", offset, hwnd );
  673. SetLastError( ERROR_INVALID_HANDLE );
  674. break;
  675. case GCL_STYLE:
  676. retvalue = reply->old_style;
  677. break;
  678. case GCL_CBWNDEXTRA:
  679. retvalue = reply->old_win_extra;
  680. break;
  681. case GCL_CBCLSEXTRA:
  682. retvalue = reply->old_extra;
  683. break;
  684. case GCL_HMODULE:
  685. retvalue = (LONG)reply->old_instance;
  686. break;
  687. case GCW_ATOM:
  688. retvalue = reply->old_atom;
  689. break;
  690. default:
  691. if (offset >= 0) memcpy( &retvalue, &reply->old_extra_value, sizeof(retvalue) );
  692. else SetLastError( ERROR_INVALID_INDEX );
  693. break;
  694. }
  695. }
  696. }
  697. SERVER_END_REQ;
  698. return retvalue;
  699. }
  700. if (offset >= 0)
  701. {
  702. if (offset <= class->cbClsExtra - sizeof(LONG))
  703. memcpy( &retvalue, (char *)(class + 1) + offset, sizeof(retvalue) );
  704. else
  705. SetLastError( ERROR_INVALID_INDEX );
  706. release_class_ptr( class );
  707. return retvalue;
  708. }
  709. switch(offset)
  710. {
  711. case GCL_HBRBACKGROUND:
  712. retvalue = (LONG)class->hbrBackground;
  713. break;
  714. case GCL_HCURSOR:
  715. retvalue = (LONG)class->hCursor;
  716. break;
  717. case GCL_HICON:
  718. retvalue = (LONG)class->hIcon;
  719. break;
  720. case GCL_HICONSM:
  721. retvalue = (LONG)class->hIconSm;
  722. break;
  723. case GCL_STYLE:
  724. retvalue = (LONG)class->style;
  725. break;
  726. case GCL_CBWNDEXTRA:
  727. retvalue = (LONG)class->cbWndExtra;
  728. break;
  729. case GCL_CBCLSEXTRA:
  730. retvalue = (LONG)class->cbClsExtra;
  731. break;
  732. case GCL_HMODULE:
  733. retvalue = (LONG)class->hInstance;
  734. break;
  735. case GCL_WNDPROC:
  736. retvalue = (LONG)CLASS_GetProc( class, WIN_PROC_32W );
  737. break;
  738. case GCL_MENUNAME:
  739. retvalue = (LONG)CLASS_GetMenuNameW( class );
  740. break;
  741. case GCW_ATOM:
  742. retvalue = (DWORD)class->atomName;
  743. break;
  744. default:
  745. SetLastError( ERROR_INVALID_INDEX );
  746. break;
  747. }
  748. release_class_ptr( class );
  749. return retvalue;
  750. }
  751. /***********************************************************************
  752. * GetClassLongA (USER32.@)
  753. */
  754. LONG WINAPI GetClassLongA( HWND hwnd, INT offset )
  755. {
  756. CLASS *class;
  757. LONG retvalue;
  758. if (offset != GCL_WNDPROC && offset != GCL_MENUNAME)
  759. return GetClassLongW( hwnd, offset );
  760. TRACE("%p %d\n", hwnd, offset);
  761. if (!(class = get_class_ptr( hwnd, FALSE ))) return 0;
  762. if (class == CLASS_OTHER_PROCESS)
  763. {
  764. FIXME( "offset %d not supported on other process window %p\n", offset, hwnd );
  765. SetLastError( ERROR_INVALID_HANDLE );
  766. return 0;
  767. }
  768. if (offset == GCL_WNDPROC)
  769. retvalue = (LONG)CLASS_GetProc( class, WIN_PROC_32A );
  770. else /* GCL_MENUNAME */
  771. retvalue = (LONG)CLASS_GetMenuNameA( class );
  772. release_class_ptr( class );
  773. return retvalue;
  774. }
  775. /***********************************************************************
  776. * SetClassWord (USER32.@)
  777. */
  778. WORD WINAPI SetClassWord( HWND hwnd, INT offset, WORD newval )
  779. {
  780. CLASS *class;
  781. WORD retval = 0;
  782. if (offset < 0) return SetClassLongA( hwnd, offset, (DWORD)newval );
  783. TRACE("%p %d %x\n", hwnd, offset, newval);
  784. if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
  785. SERVER_START_REQ( set_class_info )
  786. {
  787. req->window = hwnd;
  788. req->flags = SET_CLASS_EXTRA;
  789. req->extra_offset = offset;
  790. req->extra_size = sizeof(newval);
  791. memcpy( &req->extra_value, &newval, sizeof(newval) );
  792. if (!wine_server_call_err( req ))
  793. {
  794. void *ptr = (char *)(class + 1) + offset;
  795. memcpy( &retval, ptr, sizeof(retval) );
  796. memcpy( ptr, &newval, sizeof(newval) );
  797. }
  798. }
  799. SERVER_END_REQ;
  800. release_class_ptr( class );
  801. return retval;
  802. }
  803. /***********************************************************************
  804. * SetClassLong (USER.132)
  805. */
  806. LONG WINAPI SetClassLong16( HWND16 hwnd16, INT16 offset, LONG newval )
  807. {
  808. CLASS *class;
  809. LONG retval;
  810. HWND hwnd = (HWND)(ULONG_PTR)hwnd16; /* no need for full handle */
  811. TRACE("%p %d %lx\n", hwnd, offset, newval);
  812. switch(offset)
  813. {
  814. case GCL_WNDPROC:
  815. if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
  816. retval = (LONG)CLASS_SetProc( class, (WNDPROC)newval, WIN_PROC_16 );
  817. release_class_ptr( class );
  818. return retval;
  819. case GCL_MENUNAME:
  820. newval = (LONG)MapSL( newval );
  821. /* fall through */
  822. default:
  823. return SetClassLongA( hwnd, offset, newval );
  824. }
  825. }
  826. /***********************************************************************
  827. * SetClassLongW (USER32.@)
  828. */
  829. LONG WINAPI SetClassLongW( HWND hwnd, INT offset, LONG newval )
  830. {
  831. CLASS *class;
  832. LONG retval = 0;
  833. TRACE("%p %d %lx\n", hwnd, offset, newval);
  834. if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
  835. if (offset >= 0)
  836. {
  837. if (set_server_info( hwnd, offset, newval ))
  838. {
  839. void *ptr = (char *)(class + 1) + offset;
  840. memcpy( &retval, ptr, sizeof(retval) );
  841. memcpy( ptr, &newval, sizeof(newval) );
  842. }
  843. }
  844. else switch(offset)
  845. {
  846. case GCL_MENUNAME:
  847. CLASS_SetMenuNameW( class, (LPCWSTR)newval );
  848. retval = 0; /* Old value is now meaningless anyway */
  849. break;
  850. case GCL_WNDPROC:
  851. retval = (LONG)CLASS_SetProc( class, (WNDPROC)newval, WIN_PROC_32W );
  852. break;
  853. case GCL_HBRBACKGROUND:
  854. retval = (LONG)class->hbrBackground;
  855. class->hbrBackground = (HBRUSH)newval;
  856. break;
  857. case GCL_HCURSOR:
  858. retval = (LONG)class->hCursor;
  859. class->hCursor = (HCURSOR)newval;
  860. break;
  861. case GCL_HICON:
  862. retval = (LONG)class->hIcon;
  863. class->hIcon = (HICON)newval;
  864. break;
  865. case GCL_HICONSM:
  866. retval = (LONG)class->hIconSm;
  867. class->hIconSm = (HICON)newval;
  868. break;
  869. case GCL_STYLE:
  870. if (!set_server_info( hwnd, offset, newval )) break;
  871. retval = (LONG)class->style;
  872. class->style = newval;
  873. break;
  874. case GCL_CBWNDEXTRA:
  875. if (!set_server_info( hwnd, offset, newval )) break;
  876. retval = (LONG)class->cbWndExtra;
  877. class->cbWndExtra = newval;
  878. break;
  879. case GCL_HMODULE:
  880. if (!set_server_info( hwnd, offset, newval )) break;
  881. retval = (LONG)class->hInstance;
  882. class->hInstance = (HINSTANCE)newval;
  883. break;
  884. case GCW_ATOM:
  885. if (!set_server_info( hwnd, offset, newval )) break;
  886. retval = (DWORD)class->atomName;
  887. class->atomName = newval;
  888. break;
  889. case GCL_CBCLSEXTRA: /* cannot change this one */
  890. SetLastError( ERROR_INVALID_PARAMETER );
  891. break;
  892. default:
  893. SetLastError( ERROR_INVALID_INDEX );
  894. break;
  895. }
  896. release_class_ptr( class );
  897. return retval;
  898. }
  899. /***********************************************************************
  900. * SetClassLongA (USER32.@)
  901. */
  902. LONG WINAPI SetClassLongA( HWND hwnd, INT offset, LONG newval )
  903. {
  904. CLASS *class;
  905. LONG retval;
  906. if (offset != GCL_WNDPROC && offset != GCL_MENUNAME)
  907. return SetClassLongW( hwnd, offset, newval );
  908. TRACE("%p %d %lx\n", hwnd, offset, newval);
  909. if (!(class = get_class_ptr( hwnd, TRUE ))) return 0;
  910. if (offset == GCL_WNDPROC)
  911. retval = (LONG)CLASS_SetProc( class, (WNDPROC)newval, WIN_PROC_32A );
  912. else /* GCL_MENUNAME */
  913. {
  914. CLASS_SetMenuNameA( class, (LPCSTR)newval );
  915. retval = 0; /* Old value is now meaningless anyway */
  916. }
  917. release_class_ptr( class );
  918. return retval;
  919. }
  920. /***********************************************************************
  921. * GetClassNameA (USER32.@)
  922. */
  923. INT WINAPI GetClassNameA( HWND hwnd, LPSTR buffer, INT count )
  924. {
  925. INT ret = GlobalGetAtomNameA( GetClassLongA( hwnd, GCW_ATOM ), buffer, count );
  926. TRACE("%p %s %x\n",hwnd, debugstr_a(buffer), count);
  927. return ret;
  928. }
  929. /***********************************************************************
  930. * GetClassNameW (USER32.@)
  931. */
  932. INT WINAPI GetClassNameW( HWND hwnd, LPWSTR buffer, INT count )
  933. {
  934. INT ret = GlobalGetAtomNameW( GetClassLongW( hwnd, GCW_ATOM ), buffer, count );
  935. TRACE("%p %s %x\n",hwnd, debugstr_w(buffer), count);
  936. return ret;
  937. }
  938. /***********************************************************************
  939. * RealGetWindowClassA (USER32.@)
  940. */
  941. UINT WINAPI RealGetWindowClassA( HWND hwnd, LPSTR buffer, UINT count )
  942. {
  943. return GetClassNameA( hwnd, buffer, count );
  944. }
  945. /***********************************************************************
  946. * RealGetWindowClassW (USER32.@)
  947. */
  948. UINT WINAPI RealGetWindowClassW( HWND hwnd, LPWSTR buffer, UINT count )
  949. {
  950. return GetClassNameW( hwnd, buffer, count );
  951. }
  952. /***********************************************************************
  953. * GetClassInfoA (USER32.@)
  954. */
  955. BOOL WINAPI GetClassInfoA( HINSTANCE hInstance, LPCSTR name, WNDCLASSA *wc )
  956. {
  957. WNDCLASSEXA wcex;
  958. UINT ret = GetClassInfoExA( hInstance, name, &wcex );
  959. if (ret)
  960. {
  961. wc->style = wcex.style;
  962. wc->lpfnWndProc = wcex.lpfnWndProc;
  963. wc->cbClsExtra = wcex.cbClsExtra;
  964. wc->cbWndExtra = wcex.cbWndExtra;
  965. wc->hInstance = wcex.hInstance;
  966. wc->hIcon = wcex.hIcon;
  967. wc->hCursor = wcex.hCursor;
  968. wc->hbrBackground = wcex.hbrBackground;
  969. wc->lpszMenuName = wcex.lpszMenuName;
  970. wc->lpszClassName = wcex.lpszClassName;
  971. }
  972. return ret;
  973. }
  974. /***********************************************************************
  975. * GetClassInfoW (USER32.@)
  976. */
  977. BOOL WINAPI GetClassInfoW( HINSTANCE hInstance, LPCWSTR name, WNDCLASSW *wc )
  978. {
  979. WNDCLASSEXW wcex;
  980. UINT ret = GetClassInfoExW( hInstance, name, &wcex );
  981. if (ret)
  982. {
  983. wc->style = wcex.style;
  984. wc->lpfnWndProc = wcex.lpfnWndProc;
  985. wc->cbClsExtra = wcex.cbClsExtra;
  986. wc->cbWndExtra = wcex.cbWndExtra;
  987. wc->hInstance = wcex.hInstance;
  988. wc->hIcon = wcex.hIcon;
  989. wc->hCursor = wcex.hCursor;
  990. wc->hbrBackground = wcex.hbrBackground;
  991. wc->lpszMenuName = wcex.lpszMenuName;
  992. wc->lpszClassName = wcex.lpszClassName;
  993. }
  994. return ret;
  995. }
  996. /***********************************************************************
  997. * GetClassInfoExA (USER32.@)
  998. */
  999. BOOL WINAPI GetClassInfoExA( HINSTANCE hInstance, LPCSTR name, WNDCLASSEXA *wc )
  1000. {
  1001. ATOM atom = HIWORD(name) ? GlobalFindAtomA( name ) : LOWORD(name);
  1002. CLASS *classPtr;
  1003. TRACE("%p %s %x %p\n", hInstance, debugstr_a(name), atom, wc);
  1004. if (!hInstance) hInstance = user32_module;
  1005. if (!atom || !(classPtr = CLASS_FindClassByAtom( atom, hInstance )))
  1006. {
  1007. SetLastError( ERROR_CLASS_DOES_NOT_EXIST );
  1008. return FALSE;
  1009. }
  1010. wc->style = classPtr->style;
  1011. wc->lpfnWndProc = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32A );
  1012. wc->cbClsExtra = classPtr->cbClsExtra;
  1013. wc->cbWndExtra = classPtr->cbWndExtra;
  1014. wc->hInstance = (hInstance == user32_module) ? 0 : hInstance;
  1015. wc->hIcon = (HICON)classPtr->hIcon;
  1016. wc->hIconSm = (HICON)classPtr->hIconSm;
  1017. wc->hCursor = (HCURSOR)classPtr->hCursor;
  1018. wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
  1019. wc->lpszMenuName = CLASS_GetMenuNameA( classPtr );
  1020. wc->lpszClassName = name;
  1021. release_class_ptr( classPtr );
  1022. /* We must return the atom of the class here instead of just TRUE. */
  1023. return atom;
  1024. }
  1025. /***********************************************************************
  1026. * GetClassInfoExW (USER32.@)
  1027. */
  1028. BOOL WINAPI GetClassInfoExW( HINSTANCE hInstance, LPCWSTR name, WNDCLASSEXW *wc )
  1029. {
  1030. ATOM atom = HIWORD(name) ? GlobalFindAtomW( name ) : LOWORD(name);
  1031. CLASS *classPtr;
  1032. TRACE("%p %s %x %p\n", hInstance, debugstr_w(name), atom, wc);
  1033. if (!hInstance) hInstance = user32_module;
  1034. if (!atom || !(classPtr = CLASS_FindClassByAtom( atom, hInstance )))
  1035. {
  1036. SetLastError( ERROR_CLASS_DOES_NOT_EXIST );
  1037. return FALSE;
  1038. }
  1039. wc->style = classPtr->style;
  1040. wc->lpfnWndProc = (WNDPROC)CLASS_GetProc( classPtr, WIN_PROC_32W );
  1041. wc->cbClsExtra = classPtr->cbClsExtra;
  1042. wc->cbWndExtra = classPtr->cbWndExtra;
  1043. wc->hInstance = (hInstance == user32_module) ? 0 : hInstance;
  1044. wc->hIcon = (HICON)classPtr->hIcon;
  1045. wc->hIconSm = (HICON)classPtr->hIconSm;
  1046. wc->hCursor = (HCURSOR)classPtr->hCursor;
  1047. wc->hbrBackground = (HBRUSH)classPtr->hbrBackground;
  1048. wc->lpszMenuName = CLASS_GetMenuNameW( classPtr );
  1049. wc->lpszClassName = name;
  1050. release_class_ptr( classPtr );
  1051. /* We must return the atom of the class here instead of just TRUE. */
  1052. return atom;
  1053. }
  1054. #if 0 /* toolhelp is in kernel, so this cannot work */
  1055. /***********************************************************************
  1056. * ClassFirst (TOOLHELP.69)
  1057. */
  1058. BOOL16 WINAPI ClassFirst16( CLASSENTRY *pClassEntry )
  1059. {
  1060. TRACE("%p\n",pClassEntry);
  1061. pClassEntry->wNext = 1;
  1062. return ClassNext16( pClassEntry );
  1063. }
  1064. /***********************************************************************
  1065. * ClassNext (TOOLHELP.70)
  1066. */
  1067. BOOL16 WINAPI ClassNext16( CLASSENTRY *pClassEntry )
  1068. {
  1069. int i;
  1070. CLASS *class = firstClass;
  1071. TRACE("%p\n",pClassEntry);
  1072. if (!pClassEntry->wNext) return FALSE;
  1073. for (i = 1; (i < pClassEntry->wNext) && class; i++) class = class->next;
  1074. if (!class)
  1075. {
  1076. pClassEntry->wNext = 0;
  1077. return FALSE;
  1078. }
  1079. pClassEntry->hInst = class->hInstance;
  1080. pClassEntry->wNext++;
  1081. GlobalGetAtomNameA( class->atomName, pClassEntry->szClassName,
  1082. sizeof(pClassEntry->szClassName) );
  1083. return TRUE;
  1084. }
  1085. #endif